转换运算符重载模糊度,编译器不同 [英] conversion operator overloading ambiguity, compilers differ

查看:226
本文介绍了转换运算符重载模糊度,编译器不同的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经看到有关这方面的其他问题,但没有一个解释它。编译器如何处理以下两种情况的正确方法是什么?我试过它与gcc 4.7.1(与-std = c ++ 0x),VS2010和VS2012得到不同的结果:

I have seen other questions on SO regarding this, but none that explains it in full. What is the right ways for compilers to handle the two situations below? I have tried it with gcc 4.7.1 (with -std=c++0x), VS2010 and VS2012 an get different results on all:

示例1 :

struct BB
{
 // generic cast
 template<typename T>
 operator T() const
 {   
   return 0;
 }

 // string cast
 operator std::string() const
 { 
   return string("hello");
 }
};

int main()
{
  BB b;
  string s = b;
}

输出:


  • gcc 4.7.1:Ok

  • VS2010:Ok

  • VS2012:Fail:无法从BB转换为
    string

示例2:

struct BB
{
 // generic cast
 template<typename T>
 operator T() const
 {   
   return 0;
 }

 // string cast
 operator std::string() const
 { 
   return string("hello");
 }
};

int main()
{
  BB b;
  string s = (string)b;

输出:


  • gcc 4.7.1:失败:调用重载字符串(BB&)含糊不清

  • VS2010:Ok

  • VS2012:无法从BB转换为字符串

推荐答案

暧昧。问题是有两种方法 static_cast< std :: string> 可以将类 BB 一个字符串。明显的路径是通过使用非模板std :: string转换操作符直接转换为字符串。有一个更迂回的路径,除了VS2010都找到了。这个其他路径是使用你的模板转换操作符将 BB 转换为字符串的分配器,然后使用此分配器构造一个空字符串。

Your second version with a C-style cast is ambiguous. The problem is that there are two ways that static_cast<std::string> can convert an instance of class BB to a string. The obvious path is by using your non-template std::string cast operator to convert directly to a string. There is a more devious path, and all but VS2010 have found it. This other path is to use your template cast operator to convert a BB to an allocator for a string and then construct an empty string using this allocator.

模板操作符是潜在的危险野兽。您已经给编译器工具将 BB 转换为任何

Template cast operators are potentially dangerous beasts. You have just given the compiler the tools to convert a BB to anything.

你的第一个版本转义了这个问题,因为 std :: basic_string(const _Alloc& __a)是一个显式的构造函数。显式构造函数可以由显式转换使用,但不能由隐式转换使用。它是这个构造函数加上转换到一个分配器创建歧义,这个路径不能用于隐式转换。

Your first version escapes this problem because std::basic_string(const _Alloc& __a) is an explicit constructor. Explicit constructors can be used by explicit conversions but not by implicit ones. It is this constructor plus the conversion to an allocator that creates the ambiguity, and this path cannot be used with an implicit conversion.

至于为什么VS1012失败的隐含转换,它可能是VS2012中的一个错误,或者可能是C ++ 11创建了从 BB std的更多途径: :string 。我不是一个C ++ 11专家。我甚至不是新手。

As to why VS1012 fails on the implied conversion, it could be a bug in VS2012, or it could be that C++11 creates even more avenues to get from a BB to a std::string. I am not a C++11 expert. I'm not even a novice.

一个项目:你的代码会失败甚至更糟糕,如果你使用

One more item: your code would have failed even more miserably had you used

 std::string s;
 s = b;

赋值运算符与模板转换操作符一起创建更多方法从 b s 。如果系统将 b 转换为 std :: string ,到 char char *

The assignment operator in conjunction with the template conversion operator creates more ways to get from b to s. Should the system convert b to a std::string, to a char, or a char*?

底线:你真的应该重新考虑使用模板转换运算符。

Bottom line: You really should rethink your use of template conversion operators.

这篇关于转换运算符重载模糊度,编译器不同的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆