Joh*_*ohn 10 c++ templates operator-overloading clang sfinae
当我编译以下代码片段时,我得到了一个带有clang的编译器错误,但是没有使用g ++/MSVC:
#include <string>
template<typename T> struct Const {
explicit Const(T val) : value(val) {}
T value;
};
template<typename T> struct Var {
explicit Var(const std::string &n) : name(n) {}
std::string name;
};
template<typename L, typename R> struct Greater {
Greater(L lhs, R rhs) : left(lhs), right(rhs) {}
L left;
R right;
};
template<typename L>
Greater<L, Const<int> > operator > (L lhs, int rhs) {
return Greater<L, Const<int> >(lhs, Const<int>(rhs));
}
template<typename R>
Greater<Const<int>, R> operator > (int lhs, R rhs) {
return Greater<Const<int>, R>(Const<int>(lhs), rhs);
}
Var<double> d("d");
int main() {
d > 10;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
报告的错误如下:
error: overloaded 'operator>' must have at least one parameter of
class or enumeration type
Greater<Const<int>, R> operator > (int lhs, R rhs) {
^
./val.h:31:24: note: in instantiation of function template specialization
'operator><int>' requested here
Greater<Const<int>, R> operator > (int lhs, R rhs) {
^
1 error generated.
Run Code Online (Sandbox Code Playgroud)
这是关于未使用的操作员功能.相反,如果我写10> d而不是d> 10,那么我得到关于其他运算符>函数的相同错误.以上编译在gcc 4.4.6和VS2012下正常.我的错是什么?
谢谢.
Clang是对的:运算符重载至少需要一个类或枚举类型参数,否则程序格式不正确(13.5/1).要了解为什么会出现此错误,我们必须解析更多标准法律问题.
回想一下名称查找,参数推导和过载分辨率的三位一体.第一步发现两个重载operator>.第二步推导出每个版本的模板参数.您可能会认为第二次超载会成为SFINAE规则(14.8.2)的受害者,因此只有第一次过载才能存活到第三步.但是,没有替换失败(例如缺少嵌套的typedef),而是非法构造(参见前面提到的13.5/1).这本身就使得该计划形成不良(14.3/6)
6如果在模板专业化的实例化中使用template-argument会导致格式错误的构造,那么该程序就会形成错误.
在14.8.3中,提到对推断的参数的这种检查在重载解析之前发生,因此您的首选运算符没有被选中的机会.
作为C++ 03的解决方法,您可以operator>在Var<T>类模板中定义两个朋友非模板.这些将作为具有一个类类型参数的非模板函数注入到周围(全局,在此示例中)命名空间中,因此不应发生上述错误.
| 归档时间: |
|
| 查看次数: |
1175 次 |
| 最近记录: |