Yak*_*ont 10 c++ ambiguous assignment-operator c++14 c++17
所以我有一个提供字符串类型的现有库.
它隐式转换为C样式字符串,如下所示:
struct TypeIDoNotOwn {
TypeIDoNotOwn() {}
TypeIDoNotOwn(TypeIDoNotOwn const&) {}
TypeIDoNotOwn(char const*) {}
TypeIDoNotOwn& operator=(TypeIDoNotOwn const&) {return *this;}
TypeIDoNotOwn& operator=(char const*) {return *this;}
operator char const*() const {return nullptr;}
};
Run Code Online (Sandbox Code Playgroud)
它有其他方法,但我不认为它们很重要.这些方法有机构,但我的问题不涉及它们,所以我把它们剔除了.
我想要做的是创建一个可以与上述类型相对可互换使用的新类型,并使用"raw string constants".我希望能够获取一个实例TypeIDoNotOwn,并替换它TypeIDoOwn,并编译代码.
举个例子,这套操作:
void test( TypeIDoNotOwn const& x ) {}
int main() {
TypeIOwn a = TypeIDoNotOwn();
TypeIDoNotOwn b;
a = b;
b = a;
TypeIOwn c = "hello";
TypeIDoNotOwn d = c;
a = "world";
d = "world";
char const* e = a;
std::pair<TypeIDoNotOwn, TypeIDoNotOwn> f = std::make_pair( TypeIOwn(), TypeIOwn() );
std::pair<TypeIOwn, TypeIOwn> g = std::make_pair( TypeIDoNotOwn(), TypeIDoNotOwn() );
test(a);
}
Run Code Online (Sandbox Code Playgroud)
如果我TypeIOwn用TypeIDoNotOwn上面的替换,它编译.如何在TypeIOwn 不修改的情况下进行编译TypeIDoNotOwn?并且不必在声明点引入任何演员表或变更以外的类型更改?
我的第一次尝试看起来有点像这样:
struct TypeIOwn {
TypeIOwn() {}
operator char const*() const {return nullptr;}
operator TypeIDoNotOwn() const {return {};}
TypeIOwn( TypeIOwn const& ) {}
TypeIOwn( char const* ) {}
TypeIOwn( TypeIDoNotOwn const& ) {}
TypeIOwn& operator=( char const* ) {return *this;}
TypeIOwn& operator=( TypeIOwn const& ) {return *this;}
TypeIOwn& operator=( TypeIDoNotOwn const& ) {return *this;}
};
Run Code Online (Sandbox Code Playgroud)
但是我得到了一系列模糊的重载:
Run Code Online (Sandbox Code Playgroud)main.cpp:31:4: error: use of overloaded operator '=' is ambiguous (with operand types 'TypeIDoNotOwn' and 'TypeIOwn') b = a; ~ ^ ~ main.cpp:9:17: note: candidate function TypeIDoNotOwn& operator=(TypeIDoNotOwn const&) {return *this;} ^ main.cpp:10:17: note: candidate function TypeIDoNotOwn& operator=(char const*) {return *this;}
和
Run Code Online (Sandbox Code Playgroud)/usr/include/c++/v1/utility:315:15: error: call to constructor of 'TypeIDoNotOwn' is ambiguous : first(_VSTD::forward<_U1>(__p.first)), ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ main.cpp:40:51: note: in instantiation of function template specialization 'std::__1::pair<TypeIDoNotOwn, TypeIDoNotOwn>::pair<TypeIOwn, TypeIOwn>' requested here std::pair<TypeIDoNotOwn, TypeIDoNotOwn> f = std::make_pair( TypeIOwn(), TypeIOwn() ); ^ main.cpp:7:7: note: candidate constructor TypeIDoNotOwn(TypeIDoNotOwn const&) {} ^ main.cpp:8:7: note: candidate constructor TypeIDoNotOwn(char const*) {} ^
在我的"真实"的代码,我有其他运营商,如+=和==,有类似的问题.
真正问题的范围很大; 数以百万计的代码行,我想在数千个位置换掉TypeIDo的TypeIDoNotOwn,而不是数百个其他位置.在数千个位置,他们以导致转换模糊的方式进行交互.
我已经通过TypeIDoNotOwn&一个宏来创建一个临时对象来创建一个TypeIDoNotOwn来自TypeIOwn,返回对它的引用,然后当临时对象被销毁时将其复制回来解决了函数在100个点发生的问题.到了TypeIOwn.我想避免做类似的扫描处理==,+=,=,复制建设,类似的情况.
实例.
如果我试图删除operator TypeIDoNotOwn以消除这种歧义,那么转换需要发生的其他情况就不能正常工作(因为它需要2个用户定义的构造来TypeIOwn实现TypeIDoNotOwn),然后需要进行显式转换(在许多情况下) 100或1000个地点)
如果我可以让一个转换看起来比另一个更糟糕,它会起作用.如果做不到这一点,我可以尝试operator=通过重载一个TypeIDoNotOwn == TypeIOwn具有精确匹配的自由运算符来修复非和复制构造的情况(和其他情况类似),但这不会让我得到构造,函数调用和赋值.
通常需要注意的是,这是 C++,并且肯定有一些聪明的解决方法......不。
让我们看一下您的用例。您希望复制初始化和复制分配都起作用:
TypeIOwn a = ...;
TypeIDoNotOwn b = a; // (*)
TypeIDoNotOwn c;
c = a; // (*)
Run Code Online (Sandbox Code Playgroud)
这就需要:
operator TypeIDoNotOwn();
Run Code Online (Sandbox Code Playgroud)
如果您刚刚提供operator const char*(),则分配将起作用,但复制初始化将失败。如果您提供了两者,那么它是不明确的,因为没有办法强制一个转换优先于另一个(强制转换排序的唯一真正方法是创建类型层次结构,但您不能继承,所以您不能const char*真正强制其工作)。
一旦我们开始只使用一个转换函数,示例列表中唯一不起作用的代码是:
const char* e = a; // error: no viable conversion
Run Code Online (Sandbox Code Playgroud)
此时,您必须添加一个成员函数:
const char* e = a.c_str();
Run Code Online (Sandbox Code Playgroud)
两种pair结构都可以与一个转换函数配合使用。但仅仅通过排除法,我们就无法两者兼得。
| 归档时间: |
|
| 查看次数: |
286 次 |
| 最近记录: |