使用独立于模板的enable_if时,模板类的模板化朋友功能发生链接器错误

时间:2019-02-13 16:30:27

标签: c++ templates g++ friend-function

我正在处理带有模板化朋友功能的模板化类

model.add(LSTM(units=1,return_sequences=True,input_shape=(None,8)))
model.add(Dropout(0.2))

#model.add(LSTM(units=1,return_sequences=True,input_shape=(None,8)))                                                                                                                                               
#model.add(Dropout(0.2))                                                                                                                                                                                           

model.add(Dense(1))

model.compile(optimizer='adam',loss='mean_squared_error')

使用g ++可以正常编译,但是在链接时输入失败

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;}

使用

int main () {
  X<int> x;
  std::cout << f(x);
}

see here

我观察到的是

  • 当将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_ifintsee here时,链接成功g ++。

  • 在公开decltype(x.hidden)并删除好友声明时,代码可以很好地链接(因此,函数模板得以实例化)。

  • 删除enable_if,然后将返回类型声明为hidden即可。

  • 将enable_if从返回类型移到int,但是在这里我无法编译,因为g ++和clang ++告诉我朋友声明不允许默认模板参数。

  • 从好友声明中删除enable_if,仅将其保留在定义中→fails to link

  • 使用clang ++链接编译成功时

  • 将函数定义移动到类声明中(在现实世界的示例中失败,因为该函数应该采用各种参数作为可变参数模板,然后我违反了一个定义规则,具有{ 1}}在template <typename … , typename = typename enable_if_t<…>>定义中定义一次,在f(X<int>, X<float>)定义中定义一次。

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

1 个答案:

答案 0 :(得分: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);
}