此代码有效吗?适用于 gcc,不要与 clang 合作
Is this code valid? Works with gcc, don't work with 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;
}
这是我得到的错误:
$ 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上有虫子吗?
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在重复问题中对此进行解释。然而,我不得不多次阅读他们的回复,才明白他们的意思。我试着用这个答案来简化事情。如果我能改进,请告诉我!
- 奇怪的结构&GCC&clang(void*返回类型)
- 数据成员SFINAE的C++17测试:gcc vs clang
- 当我编译webrtc服务器时,Windows上只支持clang-cl
- 为什么在Windows上的VS 2019和Clang 9中"size_t"在没有标题的情况下工作
- 我可以将一个用clang c++11编译的对象与另一个用c++17编译的对象链接起来吗
- Clang bug?使用指针作为模板参数
- clang整洁10忽略了我的NOLINT命令
- 如何防止clang格式在流运算符调用之间添加换行符<<
- 在clang++预处理器中确定gcc工具链版本
- 为什么 Clang 不允许"and"作为函数名称?
- 带有 -stdlib=libc++ 的 clang++ 9.0.1 找不到<optional>
- clang格式:宏的缩进
- CLANG 编译器 说:变量"PTR"可能未初始化
- clang格式:禁用排序包含
- 为什么lambda在clang上崩溃而不是在gcc上崩溃
- gcc和clang在表达式是否为常量求值的问题上存在分歧
- 海湾合作委员会和Clang在lambda的constexpr-ness上存在分歧?
- clang不起作用.未定义的符号错误.代码在海湾合作委员会中罚款
- 库与 Clang 合作,但不适用于 GCC
- 此代码有效吗?适用于 gcc,不要与 clang 合作