重载常量和非常量转换运算符返回数组类型时出现 MSVC 错误 C2593
MSVC error C2593 when overloading const and non-const conversion operator returning array type
最近,我尝试使用转换运算符作为operator []
的替代方法。
像下面的代码:
#include <iostream>
class foo
{
public:
using type = int[1];
public:
operator type &() { return data; }
operator type const &() const { return data; }
private:
type data;
};
int main()
{
foo f;
f[0] = 1; // error happens here
std::cout << f[0] << std::endl;
return 0;
}
我发现它可以在G ++中工作,但在MSVCv141(2017)中不起作用。
MSVC报告:
error C2593: 'operator [' is ambiguous
note: could be 'built-in C++ operator[(foo::type, int)'
note: or 'built-in C++ operator[(const foo::type, int)'
note: while trying to match the argument list '(foo, int)'
那么这是MSVC的错误还是其他什么?以及如何解决?
这是一个MSVC错误。候选人不是模棱两可的。我想解决方法是要么为数组提供一个命名转换函数,要么只提供一个用户定义的operator[]
。
使用运算符时,我们有 [over.match.oper]:
如果任一操作数的类型是类或枚举,则可能需要声明实现此运算符的用户定义运算符函数,或者可能需要用户定义的转换才能将操作数转换为适用于内置运算符的类型。
在f[0]
中,f
具有类类型,因此我们考虑用户定义的运算符函数或用户定义的转换。没有前者,而是后者中的两个。两者都是可行的候选者:
f.operator type&()[1]; // ok
f.operator type const&()[1]; // also ok
因此,我们必须执行重载分辨率以选择最佳可行的候选者。两者之间的区别在于隐式对象参数。根据[over.match.funcs]:
为了使参数和参数列表在此异构集中具有可比性,成员函数被视为具有一个额外的参数,称为隐式对象参数,它表示已为其调用成员函数的对象。出于重载解析的目的,静态和非静态成员函数都具有隐式对象参数,但构造函数没有。
对于非静态成员函数,隐式对象参数的类型为
- "对 cv X 的左值引用",用于声明没有 ref-qualifier 或 & ref-qualifier 的函数
[ ... ] 其中 X 是函数是其成员的类,cv 是成员函数声明上的 cv 限定。[ ... ]对于转换函数,该函数被视为隐含对象参数类的成员,目的是定义隐式对象参数的类型。
因此,这里的重载分辨率就像我们有:
type& __op(foo& ); // #1
type const& __op(foo const& ); // #2
__op(f);
在这一点上,ICS排名规则告诉我们:
标准转换序列S1 是比标准转换序列 S2 更好的转换序列,如果 [ ... ]S1 和 S2 是引用绑定,引用引用的类型是相同的类型,但顶级 cv 限定符除外,并且 S2 初始化的引用引用所引用的类型比 S1 初始化的引用所引用的类型更符合 cv 条件。
#1
中的引用绑定比#2
中的引用绑定更不符合 cv 条件,因此匹配度更高。由于这是一个更好的匹配,我们最终会得到一个独特的、最可行的函数,并且调用的格式良好。
此外,让转换运算符返回指针或对数组的引用在这里应该无关紧要。基本规则是相同的,但 MSVC 允许前者。MSVC 还允许这样做:
struct foo
{
using type = int[1];
operator type& () { return data; }
operator type const& () const { return data; }
type data;
};
void call(int (&)[1]); // #1
void call(int const (&)[1]); // #2
int main()
{
foo f;
call(f); // correctly calls #1
}
- 为什么static_assert错误:即使我传递常量"expression must have a constant value"?
- NVCC 错误:string_view.h:constexpr 函数返回是非常量
- 错误:请求从"常量字符 [5]"转换为非标量类型"字符串"
- 将错误作为从字符串常量到"char*"的已弃用转换 [-Wwrite-strings]
- 错误:constexpr 变量'struct2Var'必须由常量表达式初始化
- 如何在常量计算表达式中获取编译时错误?
- 为什么定义复制构造函数会给我错误:无法将类型 'obj&' 的非常量左值引用绑定到类型为"obj"的右值?
- C++ 中常量属性的初始化构造函数错误
- 为什么我总是收到此错误:从类型为"农场动物"的右值初始化类型的非常量引用无效|
- 为什么在第二类中使用静态常量会在第一类中给出编译器错误?
- 包含常量变量并包含在多个文件中的标头的链接错误
- C++2440错误-编译器认为字符串是常量字符
- 整体模板参数。错误:在常量表达式中使用'this'
- 语法错误"常量错误"
- 常量错误为此或没有可行的重载“=”
- GCC 模板推导消除了常量错误
- 与 map 一起使用时复制构造函数常量错误
- C++如何在cpp之间与extern共享常量-错误:指定了存储类
- 字符串常量C++错误之前应为标识符
- "Discards qualifiers" C++ 中的虚函数和/或常量错误