Ambiguous overload for 'operator='
От: Trapper  
Дата: 18.09.07 16:10
Оценка:
Всем привет.
Есть такой код, который не компилиться на gcc 4.1 и на comeau (на студии VS 7.1 всё собирается замечательно):

#include <string>

struct test_struct
{
    operator bool () {return false;}
    operator std::string () {return "";}
};

int main ()
{
    std::string s;
    test_struct test;
    s = test; // вот здесь возникает ошибка
}


comeau пишет следующее:

line 13: error: more than one operator "=" matches these operands:
function "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>]"
function "std::basic_string<_CharT, _Traits,
_Alloc>::operator=(_CharT) [with _CharT=char,
_Traits=std::char_traits<char>,
_Alloc=std::allocator<char>]"
operand types are: std::string = test_struct

Я не понимаю, откуда вдруг возникла неоднозначность? Есть специально для std::string оператор преобразования. Оператор преобразования к bool хуже, т.к. для него подбирается operator=(char), а char и bool не одно и тоже. По идее должен был выбраться оператор преобразования к std::string.

Буду признателен за объяснения и/или помощь в том, как заставить компилиться этот код.
Trapper
Re: Ambiguous overload for 'operator='
От: Sharp Eye Россия  
Дата: 18.09.07 16:49
Оценка:
Здравствуйте, Trapper, Вы писали:

T>Всем привет.

T>Есть такой код, который не компилиться на gcc 4.1 и на comeau (на студии VS 7.1 всё собирается замечательно):

T>
T>#include <string>

T>struct test_struct
T>{
T>    operator bool () {return false;}
T>    operator std::string () {return "";}
T>};

T>int main ()
T>{
T>    std::string s;
T>    test_struct test;
T>    s = test; // вот здесь возникает ошибка
T>}
T>


T>comeau пишет следующее:


T>line 13: error: more than one operator "=" matches these operands:

T> function "std::basic_string<_CharT, _Traits,
T> _Alloc>::operator=(const std::basic_string<_CharT,
T> _Traits, _Alloc> &) [with _CharT=char,
T> _Traits=std::char_traits<char>,
T> _Alloc=std::allocator<char>]"
T> function "std::basic_string<_CharT, _Traits,
T> _Alloc>::operator=(_CharT) [with _CharT=char,
T> _Traits=std::char_traits<char>,
T> _Alloc=std::allocator<char>]"
T> operand types are: std::string = test_struct

T>Я не понимаю, откуда вдруг возникла неоднозначность? Есть специально для std::string оператор преобразования. Оператор преобразования к bool хуже, т.к. для него подбирается operator=(char), а char и bool не одно и тоже. По идее должен был выбраться оператор преобразования к std::string.


T>Буду признателен за объяснения и/или помощь в том, как заставить компилиться этот код.


На comeau компилится вот такое:


#include <string>

struct test_struct
{
    typedef void (test_struct::*unspecified_bool_type)();

    operator unspecified_bool_type() const
    {
        return 0;
    }

    operator std::string () {return "";}
};

int main ()
{
    std::string s;
    test_struct test;
    s = test;
}
Re[2]: Ambiguous overload for 'operator='
От: Trapper  
Дата: 18.09.07 17:17
Оценка:
SE>На comeau компилится вот такое:


SE>
SE>#include <string>

SE>struct test_struct
SE>{
SE>    typedef void (test_struct::*unspecified_bool_type)();

SE>    operator unspecified_bool_type() const
SE>    {
SE>        return 0;
SE>    }

SE>    operator std::string () {return "";}
SE>};

SE>int main ()
SE>{
SE>    std::string s;
SE>    test_struct test;
SE>    s = test;
SE>}
SE>


А можно узнать, почему оно компилиться и что всё это означает?
Да, на самом деле у меня несколько более сложный случай:

#include <string>

struct test_struct
{
    operator bool () {return false;}
    operator long () {return 0;}
    operator double () {return 0;}
    operator std::string () {return "";}
};


Хочется, чтобы такой код тоже работал.
Trapper
Re[3]: Ambiguous overload for 'operator='
От: Sharp Eye Россия  
Дата: 18.09.07 17:39
Оценка:
Здравствуйте, Trapper, Вы писали:

...

Пример:

#include <string>

class Foo;

void f(char c)
{
   std::cout << c << std::endl;
}

int main ()
{
   bool b = false;
   void (Foo::*fn_ptr)() = 0; // Указатель на метод класса

   f(b);
   f(fn_ptr); // Косяк!

   return 0;
}


Суть в том, что bool неявно конвертится в char, а вот указатель на метод — нет.
Re[3]: Ambiguous overload for 'operator='
От: Аноним  
Дата: 18.09.07 17:53
Оценка: +2
Здравствуйте, Trapper, Вы писали:

T>
T>#include <string>

T>struct test_struct
T>{
T>    operator bool () {return false;}
T>    operator long () {return 0;}
T>    operator double () {return 0;}
T>    operator std::string () {return "";}
T>};
T>


T>Хочется, чтобы такой код тоже работал.

ИМХО, такое количество операторов преобразования — это плохой стиль. Отсюда и все эти неоднозначности. Может быть определить методы to_string(), to_double() и т.д.?
Re[4]: Ambiguous overload for 'operator='
От: Awaken Украина  
Дата: 18.09.07 18:00
Оценка:
А>ИМХО, такое количество операторов преобразования — это плохой стиль. Отсюда и все эти неоднозначности.

это ужасный стиль имхо. побочные эффекты от неявных преобразований гарантированы.
если уж struct то значит все что внутри public и можно использовать напрямую.
Re: Ambiguous overload for 'operator='
От: McSeem2 США http://www.antigrain.com
Дата: 19.09.07 01:52
Оценка: 1 (1)
Здравствуйте, Trapper, Вы писали:

T>Я не понимаю, откуда вдруг возникла неоднозначность? Есть специально для std::string оператор преобразования. Оператор преобразования к bool хуже, т.к. для него подбирается operator=(char), а char и bool не одно и тоже. По идее должен был выбраться оператор преобразования к std::string.


Подобные выкрутасы являются большой gray area в C++. Их лучше не использовать, иначе проблемы с переносимостью гарантрованы.

T>Буду признателен за объяснения и/или помощь в том, как заставить компилиться этот код.


Лучше не надо заставлять. Лучше переделать так, чтобы было 100% однозначно. Выкинуть оператор bool, например.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[2]: Ambiguous overload for 'operator='
От: Trapper  
Дата: 19.09.07 03:58
Оценка:
MS>Подобные выкрутасы являются большой gray area в C++. Их лучше не использовать, иначе проблемы с переносимостью гарантрованы.

Да, как раз пришёл к такой же мысли.

T>>Буду признателен за объяснения и/или помощь в том, как заставить компилиться этот код.


MS>Лучше не надо заставлять. Лучше переделать так, чтобы было 100% однозначно. Выкинуть оператор bool, например.


Ну да, придётся идти окольными путями, хотя жаль конечно. Но всё равно
Trapper
Re[5]: Ambiguous overload for 'operator='
От: Trapper  
Дата: 19.09.07 04:04
Оценка:
Здравствуйте, Awaken, Вы писали:

А>>ИМХО, такое количество операторов преобразования — это плохой стиль. Отсюда и все эти неоднозначности.


A>это ужасный стиль имхо. побочные эффекты от неявных преобразований гарантированы.


За исключением уже описанной проблемы всё остальное работает как надо. Насчёт ужасного стиля — может быть, но делаю я так нечасто и только в тех случаях, когда это приносит ощутимую пользу, как сейчас.
Просто если делать всё стандартно, через всякие GetDouble и тд, то я лишаюсь основных преимуществ вроде выведения типа и тд. А основная цель — получить максимально удобный для использования компонент.

A>если уж struct то значит все что внутри public и можно использовать напрямую.


Не первый год замужем , инкапсуляцию использую, просто это тестовый пример
Trapper
Re[4]: Ambiguous overload for 'operator='
От: Trapper  
Дата: 19.09.07 04:06
Оценка:
SE>Суть в том, что bool неявно конвертится в char, а вот указатель на метод — нет.

Да, век живи — век учись, не знал, спасибо
Trapper
Re[6]: Ambiguous overload for 'operator='
От: artiz  
Дата: 20.09.07 09:48
Оценка:
Здравствуйте, Trapper, Вы писали:

...

T>Просто если делать всё стандартно, через всякие GetDouble и тд, то я лишаюсь основных преимуществ вроде выведения типа и тд. А основная цель — получить максимально удобный для использования компонент.


А я одобряю — только дума нужно оставить приведение к std::string, long и double как самые часто юзаемые. А если еще и [] переопределить можно деревья организовать — такая штука может быть полезна когда Composite Template реализуешь.
У нас похожая схема в двух вариантах используется, правда в .NET и с implicit — работает как в песне:

output["title"] = new Packet();
output["title"]["Item"] = "Dialog Title";
output["title"]["FontStyle"] = 1;
... << RSDN@Home 1.2.0 alpha rev. 746>>
Re[7]: Ambiguous overload for 'operator='
От: Trapper  
Дата: 20.09.07 11:35
Оценка:
Здравствуйте, artiz, Вы писали:

A>Здравствуйте, Trapper, Вы писали:


A>...


T>>Просто если делать всё стандартно, через всякие GetDouble и тд, то я лишаюсь основных преимуществ вроде выведения типа и тд. А основная цель — получить максимально удобный для использования компонент.


A>А я одобряю — только дума нужно оставить приведение к std::string, long и double как самые часто юзаемые. А если еще и [] переопределить можно деревья организовать — такая штука может быть полезна когда Composite Template реализуешь.

A>У нас похожая схема в двух вариантах используется, правда в .NET и с implicit — работает как в песне:

A>
A>output["title"] = new Packet();
A>output["title"]["Item"] = "Dialog Title";
A>output["title"]["FontStyle"] = 1;
A>


Забавно, у меня похожий случай, используется для чтения настроек — теперь выглядит приблизительно так:

int var = params["param1"] || 0; // operator || не обязателен и служит для указания дефолтового значения, когда param1 не указан в конфиге


А до этого было:

int var;
params.Get("param1", var, 0);
Trapper
Re[8]: Ambiguous overload for 'operator='
От: Erop Россия  
Дата: 20.09.07 12:26
Оценка:
Здравствуйте, Trapper, Вы писали:

T>А до этого было:


T>
T>int var;
T>params.Get("param1", var, 0);
T>


А мне как было больше нравится
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[9]: Ambiguous overload for 'operator='
От: Trapper  
Дата: 20.09.07 16:52
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, Trapper, Вы писали:


T>>А до этого было:


T>>
T>>int var;
T>>params.Get("param1", var, 0);
T>>


E>А мне как было больше нравится


На вкус и цвет — одни враги
Trapper
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.