Ошибка компоновщика с шаблонной функцией-другом шаблонного класса при использовании независимого от шаблона enable_if
Я имею дело с шаблонным классом с функцией шаблонного друга
template<typename T>
struct X {
template<typename someX>
auto friend f (someX x) -> std::enable_if_t<std::is_same_v<decltype(x.hidden), int>, int>;
private:
T hidden = 42;
};
template<typename someX>
auto f(someX x) -> std::enable_if_t<std::is_same_v<decltype(x.hidden), int>, int> {return x.hidden;}
это нормально компилируется с g++, но завершается ошибкой во время соединения в
int main () {
X<int> x;
std::cout << f(x);
}
с
prog.cc:(.text+0x15): undefined reference to `std::enable_if<is_same_v<decltype ({parm#1}.hidden), int>, int>::type f<X<int> >(X<int>)'
collect2: error: ld returned 1 exit status
То, что я заметил, это:
при замене второго аргумента
enable_if
(тип) чем-то, что зависит от шаблона класса (int
→decltype(x.hidden)
) см. здесь соединение успешно с g ++.при изготовлении
hidden
public и отбрасывая объявление друга, код прекрасно связывается (поэтому создается экземпляр шаблона функции).сбросив enable_if и просто объявив тип возвращаемого значения как
int
работает отлично.переместить enable_if из возвращаемого типа в
template <typename … , typename = typename enable_if_t<…>>
, но здесь я не могу скомпилировать, потому что g ++ и clang ++ говорят мне, что объявления друзей не допускают аргументы шаблона по умолчанию.удалите enable_if из декларации друга и оставьте только определение → не удалось установить связь
при компиляции с использованием clang ++ компоновка завершается успешно
переместить определение функции в объявление класса (в примере с реальным миром это не удается, потому что функция должна принимать различные аргументы в качестве шаблона с переменными параметрами, а затем я нарушаю правило одного определения, имея
f(X<int>, X<float>)
определяется один раз вX<int>
определение и один раз вX<float>
определение.
это ошибка g++ (8.2) или clang ++ нарушает стандарт, и в последнем случае, как запустить генерацию кода для функции?
1 ответ
это ошибка g++ (8.2) или clang++ нарушает стандарт
Я подозреваю, что GCC правильно. Шаблон друзей - это темный уголок языка.
как запустить генерацию кода для функции?
Я бы сделал это через подружившегося актера.
#include <iostream>
struct friend_of_f
{
template<class someX>
static auto apply(someX x) -> std::enable_if_t<std::is_same_v<decltype(x.hidden), int>, decltype(x.hidden)>
{
return x.hidden;
}
};
template<typename someX>
auto f(someX x) -> decltype(friend_of_f::apply(x))
{
return friend_of_f::apply(x);
}
template<typename T>
struct X
{
friend friend_of_f;
private:
T hidden = 42;
};
int main () {
X<int> x;
std::cout << f(x);
X<double> y;
// std::cout << f(y);
}