Я имею дело с шаблонным классом с функцией шаблонного друга.
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
иесли удалить объявление друга, то код прекрасно связывается (поэтому создается экземпляр шаблона функции).
, удаление enable_if и просто объявление типа возвращаемого значения как int
работает нормально.
переместить enable_if из возвращаемого типа в template <typename … , typename = typename enable_if_t<…>>
, но здесь мне не удается скомпилировать, потому что g ++ и clang ++ говорят мне, что объявления друзей не допускают аргументы шаблона по умолчанию.
удалите enable_if из объявления друга и сохраните его только в определенномiton → не может связать
, когда компиляция с использованием clang ++ успешно завершается
переместить определение функции в объявление класса (в примере с реальным миром происходит сбой, потому что функция должна принимать различные аргументы в качестве шаблона переменной, а затем я нарушаю правило одного определения, определяя f(X<int>, X<float>)
один раз в определении X<int>
и один раз в X<float>
определение.
Это ошибка g ++ (8.2) или clang ++ нарушает стандарт, и в последнем случае как мне запустить генерацию кода для функции?