使用模板独立enable_if时,链接器错误带有模板的朋友功能

linker error with templated friend function of templated class when using template independent enable_if

本文关键字:错误 朋友 功能 链接 独立 enable if      更新时间:2023-10-16

我正在使用模板的朋友函数与模板类打交道

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(类型)的第二个参数替换为依赖类模板的东西(intdecltype(x.hidden)),请参见此处的链接与G 。

  • 在公开hidden并删除朋友声明时,代码链接正常(因此函数模板得到实例化)。

  • 删除enable_if并将返回类型声明为int工作正常。

  • 将enable_if从返回类型移动到template <typename … , typename = typename enable_if_t<…>>,但是在这里我无法编译,因为G 和Clang 告诉我朋友声明不允许默认模板参数。

  • 从朋友声明中删除enable_if,仅保留在definiton→未能链接

  • 用clang 链接到成功

  • 将函数定义移动到类声明中(在现实世界中失败,因为该函数应该以各种参数作为变异模板,然后我违反了一个定义的 f(X<int>, X<float>)一次进入X<int>定义,一次在X<float>定义中。

这是g (8.2)错误还是clang 违反了标准,在后一种情况下,我如何触发该函数的代码生成?

这是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);
}