【发布时间】:2018-03-24 16:38:59
【问题描述】:
我有一个模板类Test(以整数作为模板参数)和一个模板函数(在本例中为operator*),它接受Test 类的两个对象,模板参数可能不同。该函数需要对它的两个参数都友好。这是一个最低限度的工作示例:
#include <type_traits>
template <int N>
class Test;
template <int N1, int N2>
Test<N1+N2> operator* (Test<N1>, Test<N2>);
template <int N>
class Test {
double val;
public:
Test (double x) : val{x} {}
template <int N1, int N2>
friend Test<N1+N2> operator* (Test<N1>, Test<N2>);
};
template <int N1, int N2>
Test<N1+N2> operator* (Test<N1> x, Test<N2> y) {
return Test<N1+N2> {x.val*y.val};
}
int main (int argc, char* argv[]) {
Test<1> a{4.}, c{7.9};
Test<2> b{3.5};
a*b;
a*c;
return 0;
}
这行得通,但该函数是Test 的每个专业的朋友。我只想和Test<N1> 和Test<N2> 成为朋友。
我尝试这样声明:
template <int N>
class Test {
double val;
public:
Test (double x) : val{x} {}
template <int N1, int N2>
friend std::enable_if_t<N1==N||N2==N,Test<N1+N2>> operator* (Test<N1>, Test<N2>);
};
但遇到不明确重载的 g++ 错误。我也试过了:
template <int N>
class Test {
double val;
public:
Test (double x) : val{x} {}
template <int N1, int N2, typename = std::enable_if_t<N1==N||N2==N>>
friend Test<N1+N2> operator* (Test<N1>, Test<N2>);
};
但友元声明不允许使用默认模板参数。
我更喜欢 C++14 中的解决方案,但 C++17 中的解决方案也可以接受。
更新:遵循 S.M. 的回答。我建议有类似问题的人使用以下解决方案
template <int N>
class Test {
double val;
public:
Test (double x) : val{x} {}
template <int N2>
Test<N+N2> operator* (Test<N2> y) {
return Test<N+N2> {val*y.val};
}
template <int N2>
friend class Test;
};
int main (int argc, char* argv[]) {
Test<1> a{4.}, c{7.9};
Test<2> b{3.5};
a*b;
a*c;
return 0;
}
【问题讨论】:
-
这是一个奇怪的要求。所以你希望那些不满足条件的函数存在但不能访问私有数据?一个合理的解决方案是首先禁用它们。
-
我无法理解这个要求。如果不调用
operator*,您希望它不是朋友吗?恕我直言,模棱两可是可以的。一方面是删除的运算符声明,另一方面是全局声明。编译器无法选择使用哪一个。 -
为什么
operator*<5, 3>首先会修改Test<6>的私有值?为什么你需要保护它? -
@liliscent 要了解为什么需要此要求,请在此处查看方法 #1 的问题web.mst.edu/~nmjxv3/articles/templates.html
-
@S.M.请看上面的评论
标签: c++ templates c++14 friend-function