lve*_*lla 15 c++ templates g++ clang clang++
以下最小代码在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;
}
Run Code Online (Sandbox Code Playgroud)
这是我得到的错误:
$ 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.
Run Code Online (Sandbox Code Playgroud)
铿锵3.5版.这段代码有效吗?Clang有错误吗?
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: /sf/answers/1301776661/), 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;
}
Run Code Online (Sandbox Code Playgroud)
简而言之,回答这个问题:不,代码无效。您必须阻止编译器尝试实例化::operator*<float>.
评论中的 @dyp和重复问题中的 @TemplateRex对此进行了解释。然而,我必须多次阅读他们的回复才明白他们的意思。我试图在这个答案中简化事情。如果我可以改进它,请告诉我!