以下最少代码在g ++上编译,但不会在clang ++上编译:
template<class T>
T operator*(float a, const T& b)
{
return b * a;
}
struct A{
A operator*(float b) const
{
A a;
return a;
}
};
int main()
{
A a;
2.0f * a;
}
这是我得到的错误:
$ clang++ test.cpp
test.cpp:2:3: error: overloaded 'operator*' must have at least one parameter of
class or enumeration type
T operator*(float a, const T& b)
^
test.cpp:4:11: note: in instantiation of function template specialization
'operator*<float>' requested here
return b * a;
^
test.cpp:18:10: note: in instantiation of function template specialization
'operator*<A>' requested here
2.0f * a;
^
1 error generated.
Clang版本3.5。此代码有效吗?Clang有bug吗?
2.0f * a;
实例化::operator*<A>
。在该函数中,我们有表达式b * a
,如果您查看(简化的)类型,则该表达式为A * float
。此时,编译器需要做出选择。应该*
是全局函数::operator*<float>
(因为右手参数是float
),还是应该A::operator*
?对于我们人类来说,很明显应该是A::operator*
,但是从编译器的角度来看,目前尚不清楚。
那么编译器做什么?它首先试图找到所有的operator*
,其功能可以被用来(之后,它试图确定究竟使用哪一个)。其中的一个operator*
,其功能可以被用来为::operator*<float>
。但是等等,是什么::operator*<float>
?是float *(float, const float&)
啊!而且我们不能那样做!您不能重载原始类型的运算符(如果您重载int +(int, int)
,请想象一下混乱,以便您1 + 2
做的事情与每个人都期望的完全不同)。
此时,程序格式不正确。编译器甚至尝试实例化的事实::operator*<float>
使整个程序无效。所以,我们能做些什么?告诉编译器确切的操作:
template<class T>
T operator*(float a, const T& b)
{
// This prevents the compiler from instantiating ::operator*<float>
return b.operator*(a);
// The above is meant to illustrate how the fix needs to work: it needs
// to avoid instantiating ::operator*<float>. Other methods can be used
// (like SFINAE) that might be more elegant (check out Walter's answer
// in the duplicate: https://stackoverflow.com/a/18596809/1287251), but
// in the end any solution used must avoid ::operator*<float>.
}
struct A{
A operator*(float b) const
{
A a;
return a;
}
};
int main()
{
A a;
2.0f * a;
}
简而言之,要回答这个问题:不,代码无效。您必须防止编译器尝试实例化::operator*<float>
。
这是通过在评论@dyp解释,并通过@TemplateRex在重复的问题。但是,在理解它们的含义之前,我不得不多次阅读他们的回答。我试图简化此答案中的内容。如果可以改善,请告诉我!
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句