模板运算符重载时出现奇怪错误 [英] Strange error with a templated operator overload

查看:123
本文介绍了模板运算符重载时出现奇怪错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我编译以下代码片段,我得到一个编译器错误clang,但不是与g ++ / MSVC:

When I compile the following snippet, I get a compiler error with clang, but not with 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;
}

报告的错误如下:

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.

这是关于未使用的运算符函数。如果相反,我写10> d而不是d> 10,那么我得到关于其他运算符>函数的相同的错误。以上编译精细下gcc 4.4.6和VS2012。我的错误是什么?

which is about the operator function that is not used. If, instead, I write 10 > d instead of d > 10, then I get the same error about the other operator > function. The above compiles fine under gcc 4.4.6 and VS2012. What is my mistake ?

谢谢。

推荐答案

Clang是正确的:操作符重载需要至少一个类或枚举类型参数,否则程序是不成形的/ 1)。要了解为什么这个错误甚至出现,我们必须解析一些更多的标准法律。

Clang is right: operator overloading requires at least one class or enum type parameter, otherwise the program is ill-formed (13.5/1). To see why this error even appears, we have to parse some more Standard legalese.

回忆三叉戟名称查找,参数扣除和重载分辨率。第一步找到两个重载的 operator> 。第二步推导每个版本的模板参数。您可能认为第二个重载将成为SFINAE规则(14.8.2)的牺牲品,因此只有第一个存活到第三个步骤。然而,没有替换失败(例如,例如丢失嵌套typedef),而是非法构造(参见早先提及的13.5 / 1)。 (14.3 / 6)

Recall the Holy Trinity of Name Lookup, Argument Deduction and Overload Resolution. The first step finds two overloaded operator>. The second step deduces template arguments for each version. You might think that the second overload would fall victim to the SFINAE rule (14.8.2), so that only the first survives to the third step. However, there is no substition failure (as in e.g. a missing nested typedef), but an illegal construct (see the earlier mentioned 13.5/1). That itself renders the program ill-formed (14.3/6)


6如果使用模板参数引起错误,

6 If the use of a template-argument gives rise to an ill-formed construct in the instantiation of a template specialization, the program is ill-formed.

在14.8.3中提到这个检查

In 14.8.3 it is mentioned that this check on the deduced arguments happens before overload resolution, so your preferred operator has no chance of being selected.

作为一个C ++ 03的解决方法,你可以定义两个朋友类模板中的 var 中的非模板 operator> 这些将被注入周围(全局,在这个示例中)命名空间作为具有一个类类型参数的非模板函数,因此不应该发生上述错误。

As a C++03 work-around, you could define two friend non-template operator> inside your Var<T> class template. These would be injected into the surrounding (global, in this example) namespace as non-template functions with one class type parameter, so the above error should not occur.

这篇关于模板运算符重载时出现奇怪错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆