在以下代码中,clang抱怨没有转换操作符:
class A{
public:
operator int () const {return i;}
A(int i_): i(i_) {}
template<class B>
friend auto operator * (const B& l, A&& r)
-> decltype(l * int(std::move(r))){
return l * int(std::move(r));
}
int i;
};
所有clang版本6-9都会发生这种情况,请参阅https://godbolt.org/z/ELuRHp。错误消息如下:
<source>:11:19: error: cannot convert 'typename std::remove_reference<A &>::type' (aka 'A') to
'int' without a conversion operator
-> decltype(l * int(std::move(r))){
^~~~~~~~~~~~~~~~
同一代码使用gcc 7-9编译就很好,所以我想知道这是clang中的错误还是代码不正确。
编辑:@ daniel-langr提供的同一错误的简短版本,可以在这里https://godbolt.org/z/Krnh27中找到。原始代码示例是我们代码库中类的简化版本,因此不必要的decltype
。
这看起来像是bug虫。
对于在类定义中任何地方使用的名称(包括基类说明符和嵌套类定义),但成员函数体内,成员函数的默认参数,成员函数的异常说明或默认成员除外初始化程序,其中成员可能属于嵌套类,其定义在封闭类的主体中,将搜索以下范围:
[a)在其中使用名称的类的主体,直到使用为止
...
根据上述,用户定义的转换函数必须在尾随返回类型中可见。
这是成员函数的另一个示例,该成员函数在gcc上运行良好,但在clang上不进行编译。
void f(A a, decltype(int(A)) {}