为什么这个用户定义的转换失败了?

时间:2014-12-25 21:54:53

标签: c++ c++11

此代码失败,但我认为所选的转化函数应为operator std::string(),因为它比Foo -> std::stringoperator const char*())所需的步骤少Foo -> const char* -> std::string)。

struct Foo
{
    operator const char*();
    operator std::string();
};

void f(Foo foo)
{
    std::string s2(foo); // Error!
}

标准说转换仅限于一个转换序列,转换仅在明确无误的情况下应用,那么为什么这些转换失败?

错误是:

error: call to constructor of 'std::string' (aka 'basic_string<char>') is ambiguous
    std::string s2(foo);
                ^  ~~~
note: candidate constructor
      basic_string(basic_string&& __str)
      ^
note: candidate constructor
      basic_string(const basic_string& __str);
      ^
note: candidate constructor
      basic_string(const _CharT* __s, const _Alloc& __a = _Alloc());
      ^
1 error generated.

3 个答案:

答案 0 :(得分:3)

要仅使用非显式构造函数和用户定义的转换,您应该s2 foo std::string s2 = foo; 而不是copy-initializing。{引自direct initializing

  

直接初始化比复制初始化更宽松:复制初始化仅考虑非显式构造函数和用户定义的转换函数,而直接初始化则考虑所有构造函数和隐式转换序列。

试试这个:

std::string

您现有的代码正在调用Foo的构造函数,其对象类型为foo。由于从std::string到多个{{1}}构造函数的参数类型的有效转换具有相同的转换序列长度,因此会遇到模糊问题。

答案 1 :(得分:1)

嗯,两次转化都需要一个步骤:

  • foo - &gt; char const*使用std::string::string(char const*)
  • foo - &gt; std::string使用std::string::string(std::string&&)

第三个重载是需要考虑的选项重载结果,但是采用std::string&&的构造函数比采用std::string(std::string const&)的构造函数更好,如果它们是唯一的选项,则会选择它。 / p>

目前我无法轻松测试它,但我希望

std::string s3 = foo;

希望通过std::string转换。

答案 2 :(得分:0)

错误很清楚。生成错误的行包含std::string实例的构造函数,该实例具有使用const char*std::string&复制构造函数的有效构造函数。两者都需要使用您提供的转换过载进行单个隐式转换步骤,因此它的含义是模糊的。

明确地转换对象以调用预期的转换 - 根据您的内部逻辑,const char*构造函数可能更便宜&#39;,因为std::string转换可能只返回{{1无论如何。如果是这种情况,我甚至建议删除std::string((const char*)this)转换器,因为它总是会导致模糊性,而这种模糊性永远不会更高效。