English 中文(简体)
模糊的字符串 :: operator= 调用含有内含转换成内字和字符串的类型
原标题:Ambiguous string::operator= call for type with implicit conversion to int and string

考虑到以下方案:

#include <iostream>
#include <string>
using namespace std;
struct GenericType{
   operator string(){
      return "Hello World";
   }
   operator int(){
      return 111;
   }
   operator double(){
      return 123.4;
   }
};
int main(){
   int i = GenericType();
   string s = GenericType();
   double d = GenericType();
   cout << i << s << d << endl;
   i = GenericType();
   s = GenericType(); //This is the troublesome line
   d = GenericType();
   cout << i << s << d << endl;
}

它在视觉工作室11上编译,但不是叮当或 gcc。 它遇到了麻烦, 因为它想要从 < code> GenericType 暗中转换为 < code> < int , 改为 < code>charp , 但是它也可以返回 < code>string , 因此存在模糊( operator=(char) operator=(string) 两个匹配 GenericType )。

不过,拷贝制作器还不错。

我的问题是:在不修改主内容的情况下,我如何解决这种模棱两可的问题?我需要做些什么才能修改 GenericType 来解决这个问题?

最佳回答

我相信Gcc和叮当是对的

游戏中有两个 < code> operator@/code> 超载:

string& operator=(string const& str); // (1)
string& operator=(char ch);           // (2)

这些 operator@/code>超载要求用户定义的转换,取自类型 GenericType 的参数。 < genericType > > /code > 需要使用转换为 string 的参数。 需要使用转换为 string (2) 要求使用转换为 ,然后是标准转换为 char

重要的是,两个超载都需要用户定义的转换。 要确定其中一个转换是否优于另一个转换, 我们可以查看超载解析规则, 特别是C++11 §13.3.3.2/3 (重订格式以明确) 的以下规则 :

用户定义的转换序列 U1 比另一个用户定义的转换序列 U2 要好得多,如果

  1. 它们含有相同的用户定义的转换函数或构建器或汇总初始化和

  2. U1 的第二个标准转换序列优于 U2 的第二个标准转换序列。

请注意, < em> 和 加入规则的两个部分,因此两个部分都必须满足。该规则的第一部分不能满足:两个用户定义的转换序列使用不同的用户定义的转换功能。

因此,两个转变都不如,呼吁含糊不清。

[我对如何在不改变 main () 定义的情况下解决问题没有很好的建议。 隐含转换通常不是一个好主意;它们有时非常有用,但更经常地可能造成超载含糊不清或其他奇怪的超载行为。 ]

有一份gcc错误报告描述了这一问题,并以设计方式解决了这个问题:compiler错误地诊断了超载操作员。

问题回答

我认为海合会错了。在《C++编程语言》一书《Bjarne Stroustrup的C++编程语言》中,有一章专门论述操作员超载问题。

"如果有X:Operator=(Z),V是Z,或V是独一无二的转换为Z,那么X类对象的V类价值转让是合法的。 初始化处理等同。”

以您为例, 海合会接受“ 字符串 S = GeneralType (); ”, 却拒绝“ s = GeneralType (); ”, 。 因此它显然没有像初始化一样对待指派任务。 这是我第一次发现海合会有问题。

海合会报告有3个候选人将通用字符串转换为任务字符串,全部在基本字符串.h。一个是正确的转换,一个是无效的,第三个是造成模糊不清的原因。这是操作员在基本字符串中超载,造成模糊不清:

/**
*  @brief  Set value to string of length 1.
*  @param  c  Source character.
*
*  Assigning to a character makes this string length 1 and
*  (*this)[0] == @a c.
*/
basic_string& operator=(_CharT __c) { 
    this->assign(1, __c); 
    return *this;
}

这不是有效的转换 < striction >, 因为它接受一个与传递给它的对象类型不匹配的操作。 任何地方都不像尝试的字符分配, 因此这种转换不应该是一个候选人, 更不应该造成模糊。 GCC 似乎正在将模板类型与其成员中的操作类型混合起来 。

EDIT: 我并不知道给字符串分配整数实际上是合法的, 因为整数可以转换成字符串, 可以转换成字符串( 虽然字符串不能初始化为字符! ) 。 通用Type 定义了转换成字符串, 从而使该成员成为有效的候选人 。 但是, 我仍然认为这不是一种有效的转换, 原因是使用这种转换将导致对任务进行两个用户定义的隐性转换, 首先从通用转换到 Int, 然后从 Int 到字符串。 正如同本书11. 4. 1 所说, “ 只有一等级的用户定义的隐性转换是合法的 。 ”

我的问题是:我如何在不修改主要内容的情况下解决这种模棱两可的问题?

创建名为 string 的班级,该班级没有模糊的 operator@/code>, 也没有 使用 d 之一。

显然,这不是一个非常好的解决办法,但它行之有效,而main不必改变。

我不认为你能得到你想要的行为 任何其他方式。

此解决方案工程

#include <iostream>
#include <string>
#include <type_traits>
using namespace std;
struct GenericType{

   operator string(){
      return "Hello World";
   }
   
   template <typename T, typename = std::enable_if_t <
                                    std::is_same<T, double>::value ||
                                    std::is_same<T, int>::value>>
   operator T(){
      return 123.4;
   }
};
int main(){
   int i = GenericType();
   string s = GenericType();
   double d = GenericType();
   cout << i << s << d << endl;
   i = GenericType();
   s = GenericType();
   d = GenericType();
   cout << i << s << d << endl;
}

和一个更一般的解决方案。我认为你不需要为每个算术类型创建操作员, 因为隐含的转换会起到作用。

// ...

template <typename T, typename = std::enable_if_t 
    <std::is_arithmetic<T>::value && !std::is_same<T, char>::value>>
operator T() const
{
    return std::stod("123.4");
}

//...




相关问题
Simple JAVA: Password Verifier problem

I have a simple problem that says: A password for xyz corporation is supposed to be 6 characters long and made up of a combination of letters and digits. Write a program fragment to read in a string ...

Case insensitive comparison of strings in shell script

The == operator is used to compare two strings in shell script. However, I want to compare two strings ignoring case, how can it be done? Is there any standard command for this?

Trying to split by two delimiters and it doesn t work - C

I wrote below code to readin line by line from stdin ex. city=Boston;city=New York;city=Chicago and then split each line by ; delimiter and print each record. Then in yet another loop I try to ...

String initialization with pair of iterators

I m trying to initialize string with iterators and something like this works: ifstream fin("tmp.txt"); istream_iterator<char> in_i(fin), eos; //here eos is 1 over the end string s(in_i, ...

break a string in parts

I have a string "pc1|pc2|pc3|" I want to get each word on different line like: pc1 pc2 pc3 I need to do this in C#... any suggestions??

Quick padding of a string in Delphi

I was trying to speed up a certain routine in an application, and my profiler, AQTime, identified one method in particular as a bottleneck. The method has been with us for years, and is part of a "...