Насколько оправданы жалобы компилятора на ambiguous conversion
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 10.10.17 10:09
Оценка:
Есть у меня несколько классов, сутью которых являются 64-разрядные целые значения — например, 64-разрядный атомарный счетчик, который может быть интерпретирован как знаковый или беззнаковый, а также как 32-разрядный (по младшей части). Но MSVC 15.00 (из VS 2008) категорически отказывается сам выполнять вполне очевидные преобразования.

Если для user-defined conversion я определяю только операторы преобразования к [unsigned] __int64, то компилятор жалуется на неоднозначность автоматического преобразования при сравнении с нулем или положительной литеральной константой. Если добавляю определение операторов сравнения — начинает жаловаться на неоднозначность выбора такого оператора. В этом вообще есть хоть какой-то смысл? То есть, есть живые архитектуры, на которых знаковый и беззнаковый нуль имеет различное двоичное представление?

Если же добавляю, например, операторы += для [unsigned] __int64, то начинаются жалобы на неоднозначность даже при тупом присваивании объекту значения переменной типа unsigned int. Уж если правый операнд четко имеет тип unsigned int, то логично преобразовывать его в unsigned __int64, а не просто в __int64?

Можно ли как-то заставить компилятор проявлять чуть больше интеллекта, кроме как специализировать классы конкретными типами через шаблоны?
user-defined conversion преобразование тип класс неоднозначность
Re: Насколько оправданы жалобы компилятора на ambiguous conversion
От: uzhas Ниоткуда  
Дата: 10.10.17 10:20
Оценка: +2
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Есть у меня несколько классов


вместо многобукв лучше бы выложил пример кода в ideone и спросил, как убрать ошибку компиляции
Re[2]: Насколько оправданы жалобы компилятора на ambiguous conversion
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 10.10.17 10:48
Оценка:
Здравствуйте, uzhas, Вы писали:

U>вместо многобукв лучше бы выложил пример кода


  Код
class C64 {

  unsigned __int64 Value;

  public:

  C64 () : Value (0) { }

  operator unsigned __int64 () const { return Value; }
  operator __int64 () const { return Value; }
  void operator = (unsigned __int64 S) { Value = S; }
  void operator = (__int64 S) { Value = S; }

};

void f () {

  C64 c;

  int i = 0;
  unsigned int ui = 0;

  bool b = (c == 0);

  c = i;
  c = ui;

}

  Результат
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.207 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.

convops.cpp
convops.cpp(23) : error C2593: 'operator ==' is ambiguous
could be 'built-in C++ operator==(unsigned __int64, int)'
or 'built-in C++ operator==(__int64, int)'
while trying to match the argument list '(C64, int)'
convops.cpp(25) : error C2593: 'operator =' is ambiguous
convops.cpp(12): could be 'void C64::operator =(__int64)'
convops.cpp(11): or 'void C64::operator =(unsigned __int64)'
while trying to match the argument list '(C64, int)'
convops.cpp(26) : error C2593: 'operator =' is ambiguous
convops.cpp(12): could be 'void C64::operator =(__int64)'
convops.cpp(11): or 'void C64::operator =(unsigned __int64)'
while trying to match the argument list '(C64, unsigned int)'
Re[3]: Насколько оправданы жалобы компилятора на ambiguous conversion
От: uzhas Ниоткуда  
Дата: 10.10.17 11:03
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>[cut=Код]


лучше так: https://ideone.com/ljgKea
Re[4]: Насколько оправданы жалобы компилятора на ambiguous conversion
От: uzhas Ниоткуда  
Дата: 10.10.17 11:18
Оценка: +1
Здравствуйте, uzhas, Вы писали:

U>лучше так: https://ideone.com/ljgKea


так пробовал? https://ideone.com/PLVF5C
какие дальнейшие проблемы с этим кодом?
Re[3]: Насколько оправданы жалобы компилятора на ambiguous c
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 10.10.17 11:19
Оценка: +1
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Здравствуйте, uzhas, Вы писали:


U>>вместо многобукв лучше бы выложил пример кода

Почему ты такой ленивый и не сделал как тебя просили?
Определи свой оператор сравнения. Тут проблема в том, что компилятор не может выбрать правильную перегрузку, но если ты сам определишь оператор сравнения
 bool operator==(const C64&, unsigned int);

то всё заработает.
Sic luceat lux!
Отредактировано 10.10.2017 11:20 Kernan . Предыдущая версия .
Re[4]: Насколько оправданы жалобы компилятора на ambiguous c
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 10.10.17 11:29
Оценка:
Здравствуйте, Kernan, Вы писали:

K>Определи свой оператор сравнения.


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

K>Тут проблема в том, что компилятор не может выбрать правильную перегрузку


Вот я и спрашиваю, в чем проблема. То есть, чем, с точки зрения компилятора, отличаются знаковый и беззнаковый нуль, и что ему мешает, при наличии явно определенного преобразования беззнакового 32-разрядного к беззнаковому же 64-разрядному, рассматривать еще и вариант преобразования в знаковое 64-разрядное.

Я не понимаю этой логики. Известны ли примеры, в которых естественным и интуитивно логичным будет как раз неявное преобразование беззнакового к знаковому?
Re[3]: Насколько оправданы жалобы компилятора на ambiguous c
От: night beast СССР  
Дата: 10.10.17 11:35
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

U>>вместо многобукв лучше бы выложил пример кода


  Код
ЕМ>
ЕМ>class C64 {

ЕМ>  unsigned __int64 Value;

ЕМ>  public:

ЕМ>  C64 () : Value (0) { }

ЕМ>  operator unsigned __int64 () const { return Value; }
ЕМ>  operator __int64 () const { return Value; }
ЕМ>  void operator = (unsigned __int64 S) { Value = S; }
ЕМ>  void operator = (__int64 S) { Value = S; }

ЕМ>};

ЕМ>void f () {

ЕМ>  C64 c;

ЕМ>  int i = 0;
ЕМ>  unsigned int ui = 0;

ЕМ>  bool b = (c == 0);

ЕМ>  c = i;
ЕМ>  c = ui;

ЕМ>}
ЕМ>


нет возможности проверить на студии.
template<typename T, typename C = enable_if_t<is_integral<T>::value>>
using enable_integral = T;

class C64 {

  // сравнение
  template<typename T>
  friend bool operator == (C64 l, enable_integral<T> r) { return l.Value == r; }

  template<typename T>
  friend bool operator == (enable_integral<T> l, C64 r) { return l == r.Value; }

  // каст
  template<typename T>
  operator enable_integral<T> () const { return Value; }

  // присвоение
  template<typename T>
  void operator = (enable_integral<T> S) { Value = S; }
};
Отредактировано 10.10.2017 11:36 night beast . Предыдущая версия .
Re[4]: Насколько оправданы жалобы компилятора на ambiguous c
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 10.10.17 14:19
Оценка:
Здравствуйте, night beast, Вы писали:

NB>template<typename T, typename C = enable_if_t<is_integral<T>::value>>

NB>using enable_integral = T;

Я ж подчеркнул, что хотелось бы обойтись без шаблонов и их специализации. Ну и синтаксиса такого VC++ 15.00 не поймет.
Re[5]: Насколько оправданы жалобы компилятора на ambiguous c
От: rg45 СССР  
Дата: 10.10.17 14:26
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Я ж подчеркнул, что хотелось бы обойтись без шаблонов и их специализации. Ну и синтаксиса такого VC++ 15.00 не поймет.


std::enable_if заменяется на boost::enable_if, и все.
--
Справедливость выше закона. А человечность выше справедливости.
Re[4]: Насколько оправданы жалобы компилятора на ambiguous c
От: rg45 СССР  
Дата: 10.10.17 14:37
Оценка:
Здравствуйте, night beast, Вы писали:

NB>нет возможности проверить на студии.

template<typename T, typename C = enable_if_t<is_integral<T>::value>>
using enable_integral = T;


Я сталкивался с тем, что студия игнорирует второй параметр шаблона, как неиспользумый. А чтобы этого избежать, вместо using нужно определить полный класс — чтобы образовалась инстанцируемая сущность.
--
Справедливость выше закона. А человечность выше справедливости.
Re[6]: Насколько оправданы жалобы компилятора на ambiguous c
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 10.10.17 14:39
Оценка:
Здравствуйте, rg45, Вы писали:

R>std::enable_if заменяется на boost::enable_if, и все.


Так все равно ж придется специализировать шаблон для каждого типа. И все равно останутся проблемы с прибавлением к 64-разрядному счетчику 32-разрядных значений, которые компилятор будто бы не знает, как правильно расширить.

Получается, что нечеловеческие ограничения требуют нечеловеческих способов для устранения. Грустно.
Re[7]: Насколько оправданы жалобы компилятора на ambiguous c
От: night beast СССР  
Дата: 10.10.17 16:27
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

R>>std::enable_if заменяется на boost::enable_if, и все.


ЕМ>Так все равно ж придется специализировать шаблон для каждого типа. И все равно останутся проблемы с прибавлением к 64-разрядному счетчику 32-разрядных значений, которые компилятор будто бы не знает, как правильно расширить.


не понимаю, о каких специализациях речь.
is_integral и enable_if из стандартной библиотеки.
ну и нужны они чтобы левые типы отсеять. а так можно и без них. где надо компилятор обругает.
Re[8]: Насколько оправданы жалобы компилятора на ambiguous c
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 11.10.17 04:30
Оценка:
Здравствуйте, night beast, Вы писали:

NB>не понимаю, о каких специализациях речь.


Был единственный класс C64, а теперь потребуются его варианты для каждого T.

NB>is_integral и enable_if из стандартной библиотеки.


VC++ 15.00 из VS 2008 не понимает такого синтаксиса template/using:

error C2988: unrecognizable template declaration/definition
error C2059: syntax error : 'using'

Re[9]: Насколько оправданы жалобы компилятора на ambiguous c
От: night beast СССР  
Дата: 11.10.17 08:14
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

NB>>не понимаю, о каких специализациях речь.


ЕМ>Был единственный класс C64, а теперь потребуются его варианты для каждого T.


зачем? тебе надо по разному обрабатывать разные типы?
Re[10]: Насколько оправданы жалобы компилятора на ambiguous c
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 11.10.17 08:25
Оценка:
Здравствуйте, night beast, Вы писали:

NB>тебе надо по разному обрабатывать разные типы?


Нет, но из шаблонного класса с параметром как-то должен получиться обычный класс без параметра.

Или это расширение, введенное в C++11 или позже — я, честно говоря, давно не слежу за нововведениями в языке, мне нужна совместимость с VS 2008, максимум — с VS 2010.
Re[7]: Насколько оправданы жалобы компилятора на ambiguous c
От: uzhas Ниоткуда  
Дата: 11.10.17 09:09
Оценка: +2
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Получается, что нечеловеческие ограничения требуют нечеловеческих способов для устранения. Грустно.


Да, требуется напрячься, много копи-пасты. И да, неявные преобразования (operator bla-bla) в общем случае — это плохо, особенно если у класса их не одна штука. Будешь долго разгребать сюрпризы.
Re[11]: Насколько оправданы жалобы компилятора на ambiguous c
От: night beast СССР  
Дата: 11.10.17 09:36
Оценка: +1
Здравствуйте, Евгений Музыченко, Вы писали:

NB>>тебе надо по разному обрабатывать разные типы?


ЕМ>Нет, но из шаблонного класса с параметром как-то должен получиться обычный класс без параметра.


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

ЕМ>Или это расширение, введенное в C++11 или позже — я, честно говоря, давно не слежу за нововведениями в языке, мне нужна совместимость с VS 2008, максимум — с VS 2010.


да нет, еще с 98. только раньше меньше возможностей было. простой вариант
  template<typename T>
  void operator = (T S) { Value = S; }

должна и 2008 студия переварить.
Re[8]: Насколько оправданы жалобы компилятора на ambiguous c
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 11.10.17 15:52
Оценка:
Здравствуйте, uzhas, Вы писали:

U>Да, требуется напрячься, много копи-пасты.


Напрячься — не проблема, а вот результаты копипасты выглядят чересчур громоздко и избыточно.

U>И да, неявные преобразования (operator bla-bla) в общем случае — это плохо


Плохо оно только в принятой нечеловеческой реализации. По уму, нужно было сразу вводить средства управления приоритетом и пределами преобразований для наиболее очевидных случаев. Идея хорошая, реализация — дерьмо.
Re[12]: Насколько оправданы жалобы компилятора на ambiguous c
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 11.10.17 15:54
Оценка:
Здравствуйте, night beast, Вы писали:

NB>
NB>  template<typename T>
NB>  void operator = (T S) { Value = S; }
NB>


NB>должна и 2008 студия переварить.


Точно, где-то с 98-2003 поддерживается. Упомянуто только в одном месте документации, куда не изо всех связанных разделов есть ссылки. Спасибо, это весьма облегчает жизнь.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.