Оператор преобразования C ++ с перегрузкой для пользовательского типа в std :: string

Я надеюсь, что кто-то сможет ответить, почему следующее не работает. Терпите меня, хотя, я все еще очень нуб ... Я просто не могу понять, почему следующее

using namespace std;
#include <string>
#include <iostream>

class testClass
{
public:
 operator char* () {return (char*)"hi";};
 operator int ()  {return 77;};
 operator std::string  () {return "hello";};
};

int main()
{
 char* c;
 int i;
 std::string s = "goodday";

 testClass t;

 c = t;
 i = t;
 s = t;

 cout<< "char: " << c << " int: " << i << " string: "<<s<<endl;

 return 0;
}

дает мне ошибку времени компиляции:

myMain.cpp: In function ‘int main()’:
myMain.cpp:23: error: ambiguous overload for ‘operator=’ in ‘s = t’
/usr/include/c++/4.2.1/bits/basic_string.h:500: note: candidates are: std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT, _Traits, _Alloc>::operator=(const std::basic_string<_CharT, _Traits, _Alloc>&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]
/usr/include/c++/4.2.1/bits/basic_string.h:508: note:                 std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT, _Traits, _Alloc>::operator=(const _CharT*) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]
/usr/include/c++/4.2.1/bits/basic_string.h:519: note:                 std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT, _Traits, _Alloc>::operator=(_CharT) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]

Если я не пытаюсь выполнить присвоение

s = t;

, это работает.

Я пытался часами даже Я понимаю сообщение об ошибке, но больше всего меня озадачивает то, что он работает для char *.

Я благодарен за любую подсказку. Спасибо! Маркус

14
задан Matthew Flaschen 19 August 2010 в 01:53
поделиться

5 ответов

Не существует точного std :: string :: operator =. Перефразированные кандидаты:

s = (const std::string)(std::string)t;
s = (const char*)t;
s = (char)(int)t;

Я думаю, что все будет работать, если вы измените его так, чтобы он возвращал const std :: string. ( РЕДАКТИРОВАТЬ: Я ошибаюсь.) Также обратите внимание, что первая функция должна возвращать const char *. Если вам нужно преобразовать строковый литерал в char *, вы делаете что-то не так; строковые литералы не записываются.

3
ответ дан 1 December 2019 в 12:12
поделиться

Хорошо, уже всем большое спасибо. Думаю, я начинаю понимать, что-то вроде ...

Прежде всего, я не знал, что char - это всего лишь 8-битное целое число. Спасибо за это разъяснение.

Итак, я понимаю, что, поскольку для std :: string определены три оператора присваивания, каждый с разными аргументами (string, char *, const char *), правая часть моего выражения

s=t

не знать, в какой тип нужно преобразовать, поскольку существует несколько потенциально совпадающих (для этого присвоения std :: string) преобразований, определенных с помощью

operator int ()  {return 77;};
operator std::string  () {return "hello";};

(поскольку char: 8bit int)

или

operator char* () {return (char*)"hi";};
operator std::string  () {return "hello";};

Это правильно? Итак, с точки зрения идиотов, левая часть присваивания не сообщает правой части, какой тип она ожидает, поэтому rhs должен выбирать из своих вариантов, где один так же хорош, как другой? std :: string operator = является толерантным для моих намерений?

Пока все хорошо, я думал, что понял - но тогда почему следующее также создает двусмысленность?

 using namespace std;
 #include <string>
 #include <iostream>

 class testClass
  {
   public:
     operator float ()  {return float(77.333);};
     operator std::string  () {return "hello";};
  };

  int main()
  {
    std::string s = "goodday";
    testClass t;

    s = t;

    cout<< " string: "<<s <<endl;

    return 0;
  }

Теперь есть только одно совпадающее преобразование оператор определенный мной, не так ли? std :: string operator = не может принимать числа с плавающей запятой, или может? Или float каким-то образом снова эквивалентен некоторому варианту char?

Я понимаю код как 's =', говорящий rhs: «дай мне строку, char * или const char *»

Rhs проверяет, что это может предоставить данный экземпляр testClass, и единственное соответствие - testClass :: operator std :: string

Опять же, спасибо за ваше терпение, опыт и время, ребята - я очень ценю это.

0
ответ дан 1 December 2019 в 12:12
поделиться

На самом деле это потому, что std :: string предлагает оператор присваивания, который принимает const char * .

1
ответ дан 1 December 2019 в 12:12
поделиться

What the error is trying to explain is that your assignment "s = t", where s is a std: :string, would be valid if t were a std::string too, or if t were a [const] char*. Your conversion operators can convert a t into either, so the compiler has no basis on which to choose one over the other....

Вы можете сделать это явно, выбрав нужное вам преобразование:

s = t.operator std::string();
s = static_cast<std::string>(t);

Или вы можете предоставить только одно из преобразований и позволить пользователю выполнить дальнейшее преобразование, когда это необходимо.

Однако в конце концов вы можете обнаружить, что любой оператор преобразования доставляет больше проблем, чем того стоит... показательно, что std::string сам по себе не предоставляет оператора преобразования в const char*.

11
ответ дан 1 December 2019 в 12:12
поделиться

$ 13.3.1.5 / 2 состояния- "Преобразование функции S и его базовых классов считаются. Те, что не скрыто внутри S и дает тип T или тип, который можно преобразовать в тип T через стандартную последовательность преобразования (13.3.3.1.1) - функции-кандидаты. Функции преобразования, возвращающие cv-квалифицированный тип считается дать cv-неквалифицированную версию этот тип для этого процесса выбор функций-кандидатов. Функции преобразования, возвращающие «Ссылка на cv2 X» возвращает lvalue введите «cv2 X» и поэтому считается, что дает X для этого процесса выбора функций-кандидатов »

Присваивание s = t работает следующим образом:

a) Учитываются все члены типа« t »(testClass), которые могут преобразовывать« t »в« s ».

Candidate 1: operator string();   // s created using member string::operator=(string const&)
Candidate 2: operator char *()    // s created using member string::operator=(char const*)
Candidate 3: operator char *()    // s created using member string::operator=(char *)

б) Все вышеперечисленные кандидаты жизнеспособны (то есть, в отсутствие других кандидатов компилятор может успешно разрешить вызов функции любому из них)

в) Однако теперь необходимо определить лучший жизнеспособный кандидат. Последовательности преобразования:

Candidate 1: U1 : operator string()
Candidate 2: U2 : operator char*()->const qualification to match string::operator=(char const*)
Candidate 3: U3 : operator char*()

$ 13.3.3.1.1/3 штатов - «Ранг последовательность преобразования определяется учитывая ранг каждого преобразование в последовательности и ранг любой ссылочной привязки (13.3.3.1.4). Если у кого-то из них Ранг конверсии, последовательность имеет Ранг преобразования; "

Это означает, что все U1, U2 и U3 имеют ранг преобразования и на первом уровне ни один из них не лучше другого. Однако в стандарте также указано

Пользовательская последовательность преобразования U1 является лучшая последовательность преобразования, чем другое определяемое пользователем преобразование последовательность U2, если они содержат одинаковые определяемая пользователем функция преобразования или конструктор и если второй стандарт последовательность преобразования U1 лучше чем второе стандартное преобразование последовательность U2.

Итак, давайте посмотрим, что это значит.

Между U1 и U2 они включают разные функции преобразования, и, следовательно, ни одна из них не лучше другой

Между U1 и U3 они включают разные функции преобразования, и, следовательно, ни одна из них не лучше другой

Так что насчет U1 и U2. Они включают ту же функцию преобразования, которая удовлетворяет первой части условия «и» выше

Так что насчет части «и если вторая стандартная последовательность преобразования U1 лучше, чем вторая стандартная последовательность преобразования U2.»

В U2 для второй стандартной последовательности преобразования требуется квалификация const, тогда как в U3 этого не требуется. Вторая стандартная последовательность преобразования U3 - это точное соответствие.

Но, как указано в Таблице 9 в Стандарте, квалификация CV также считается точным соответствием.

Следовательно, U2 и U3 также действительно неразличимы с точки зрения разрешения перегрузки.

Это означает, что U1, U2 и U3 действительно не хуже друг друга, и компилятор считает разрешение вызова (как часть оператора присваивания) неоднозначным, так как не существует однозначной лучшей жизнеспособной функции

9
ответ дан 1 December 2019 в 12:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: