Есть у меня несколько классов, сутью которых являются 64-разрядные целые значения — например, 64-разрядный атомарный счетчик, который может быть интерпретирован как знаковый или беззнаковый, а также как 32-разрядный (по младшей части). Но MSVC 15.00 (из VS 2008) категорически отказывается сам выполнять вполне очевидные преобразования.
Если для user-defined conversion я определяю только операторы преобразования к [unsigned] __int64, то компилятор жалуется на неоднозначность автоматического преобразования при сравнении с нулем или положительной литеральной константой. Если добавляю определение операторов сравнения — начинает жаловаться на неоднозначность выбора такого оператора. В этом вообще есть хоть какой-то смысл? То есть, есть живые архитектуры, на которых знаковый и беззнаковый нуль имеет различное двоичное представление?
Если же добавляю, например, операторы += для [unsigned] __int64, то начинаются жалобы на неоднозначность даже при тупом присваивании объекту значения переменной типа unsigned int. Уж если правый операнд четко имеет тип unsigned int, то логично преобразовывать его в unsigned __int64, а не просто в __int64?
Можно ли как-то заставить компилятор проявлять чуть больше интеллекта, кроме как специализировать классы конкретными типами через шаблоны?
Здравствуйте, 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, Вы писали:
U>>вместо многобукв лучше бы выложил пример кода
Почему ты такой ленивый и не сделал как тебя просили?
Определи свой оператор сравнения. Тут проблема в том, что компилятор не может выбрать правильную перегрузку, но если ты сам определишь оператор сравнения
Здравствуйте, Kernan, Вы писали:
K>Определи свой оператор сравнения.
Я знаю, что можно определить операторы сравнения на каждый случай, но для всех возможных вариантов это слишком громоздко.
K>Тут проблема в том, что компилятор не может выбрать правильную перегрузку
Вот я и спрашиваю, в чем проблема. То есть, чем, с точки зрения компилятора, отличаются знаковый и беззнаковый нуль, и что ему мешает, при наличии явно определенного преобразования беззнакового 32-разрядного к беззнаковому же 64-разрядному, рассматривать еще и вариант преобразования в знаковое 64-разрядное.
Я не понимаю этой логики. Известны ли примеры, в которых естественным и интуитивно логичным будет как раз неявное преобразование беззнакового к знаковому?
Re[3]: Насколько оправданы жалобы компилятора на ambiguous c
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Я ж подчеркнул, что хотелось бы обойтись без шаблонов и их специализации. Ну и синтаксиса такого VC++ 15.00 не поймет.
std::enable_if заменяется на boost::enable_if, и все.
--
Справедливость выше закона. А человечность выше справедливости.
Re[4]: Насколько оправданы жалобы компилятора на ambiguous c
Здравствуйте, night beast, Вы писали:
NB>нет возможности проверить на студии.
template<typename T, typename C = enable_if_t<is_integral<T>::value>>
using enable_integral = T;
Я сталкивался с тем, что студия игнорирует второй параметр шаблона, как неиспользумый. А чтобы этого избежать, вместо using нужно определить полный класс — чтобы образовалась инстанцируемая сущность.
--
Справедливость выше закона. А человечность выше справедливости.
Re[6]: Насколько оправданы жалобы компилятора на ambiguous c
Здравствуйте, rg45, Вы писали:
R>std::enable_if заменяется на boost::enable_if, и все.
Так все равно ж придется специализировать шаблон для каждого типа. И все равно останутся проблемы с прибавлением к 64-разрядному счетчику 32-разрядных значений, которые компилятор будто бы не знает, как правильно расширить.
Получается, что нечеловеческие ограничения требуют нечеловеческих способов для устранения. Грустно.
Re[7]: Насколько оправданы жалобы компилятора на ambiguous c
Здравствуйте, Евгений Музыченко, Вы писали:
R>>std::enable_if заменяется на boost::enable_if, и все.
ЕМ>Так все равно ж придется специализировать шаблон для каждого типа. И все равно останутся проблемы с прибавлением к 64-разрядному счетчику 32-разрядных значений, которые компилятор будто бы не знает, как правильно расширить.
не понимаю, о каких специализациях речь.
is_integral и enable_if из стандартной библиотеки.
ну и нужны они чтобы левые типы отсеять. а так можно и без них. где надо компилятор обругает.
Re[8]: Насколько оправданы жалобы компилятора на ambiguous c
Здравствуйте, Евгений Музыченко, Вы писали:
NB>>не понимаю, о каких специализациях речь.
ЕМ>Был единственный класс C64, а теперь потребуются его варианты для каждого T.
зачем? тебе надо по разному обрабатывать разные типы?
Re[10]: Насколько оправданы жалобы компилятора на ambiguous c
Здравствуйте, night beast, Вы писали:
NB>тебе надо по разному обрабатывать разные типы?
Нет, но из шаблонного класса с параметром как-то должен получиться обычный класс без параметра.
Или это расширение, введенное в C++11 или позже — я, честно говоря, давно не слежу за нововведениями в языке, мне нужна совместимость с VS 2008, максимум — с VS 2010.
Re[7]: Насколько оправданы жалобы компилятора на ambiguous c
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Получается, что нечеловеческие ограничения требуют нечеловеческих способов для устранения. Грустно.
Да, требуется напрячься, много копи-пасты. И да, неявные преобразования (operator bla-bla) в общем случае — это плохо, особенно если у класса их не одна штука. Будешь долго разгребать сюрпризы.
Re[11]: Насколько оправданы жалобы компилятора на ambiguous c
Здравствуйте, Евгений Музыченко, Вы писали:
NB>>тебе надо по разному обрабатывать разные типы?
ЕМ>Нет, но из шаблонного класса с параметром как-то должен получиться обычный класс без параметра.
нет шаблонного класса. есть класс с шаблонными функциями, которые инстанцируются (генерируются) по мере необходимости.
в твоем случае, скорее всего, еще и заинлайнятся.
ЕМ>Или это расширение, введенное в C++11 или позже — я, честно говоря, давно не слежу за нововведениями в языке, мне нужна совместимость с VS 2008, максимум — с VS 2010.
да нет, еще с 98. только раньше меньше возможностей было. простой вариант
Здравствуйте, uzhas, Вы писали:
U>Да, требуется напрячься, много копи-пасты.
Напрячься — не проблема, а вот результаты копипасты выглядят чересчур громоздко и избыточно.
U>И да, неявные преобразования (operator bla-bla) в общем случае — это плохо
Плохо оно только в принятой нечеловеческой реализации. По уму, нужно было сразу вводить средства управления приоритетом и пределами преобразований для наиболее очевидных случаев. Идея хорошая, реализация — дерьмо.
Re[12]: Насколько оправданы жалобы компилятора на ambiguous c
Точно, где-то с 98-2003 поддерживается. Упомянуто только в одном месте документации, куда не изо всех связанных разделов есть ссылки. Спасибо, это весьма облегчает жизнь.