потому что неправильно используете
после использование енума как еррор кода его нельзя сравнивать
сравнивайте и используйте везде по коду std::error_code
а иначе какой смысл в том что вы делаете ?
ну или можете свой min в том месте определить, но это уг
Re[2]: is_error_code_enum - error: specialization after instantiation
Здравствуйте, reversecode, Вы писали:
R>потому что неправильно используете R>после использование енума как еррор кода его нельзя сравнивать
? Хотелось бы подробностей. Я так понимаю проблема в том, что сравнение стало приводит к инстанцированию is_error_code_enum<status> до его специализации. Почему? В смысле почему приводит, а не почему до специализации.
In all cases, for the built-in operators, lhs and rhs must have either
arithmetic or enumeration type (see arithmetic comparison operators below)
...
If the operands have arithmetic or enumeration type (scoped or unscoped), usual arithmetic conversions are performed on both operands following the rules for arithmetic operators. The values are compared after conversions:
an unscoped enumeration type whose underlying type is not fixed can be converted to the first type from the following list able to hold their entire value range: int, unsigned int, long, unsigned long, long long, or unsigned long long, extended integer types with higher conversion rank (in rank order, signed given preference over unsigned) (since C++11). If the value range is greater, no integral promotions apply;
an unscoped enumeration type whose underlying type is fixed can be converted to its underlying type, and, if the underlying type is also subject to integral promotion, to the promoted underlying type. Conversion to the unpromoted underlying type is better for the purposes of overload resolution;
Т.е. я так понимал, что сравнение enum'а идет через встроенное сравнение как арифметического типа. Судя по всему это не так. Хотелось бы понять почему. Выглядит так, что есть нек. глобальный шаблонный оператор сравнения, который enable_if<is_error_code_enum<T>::value>. При этом если заменить std::min именно на ручное сравнение, напр.
s1 < s2 ? s1 : s2;
не воспроизводится, как и при -O0 или -std=gnu++11? Что почейтать?
R>сравнивайте и используйте везде по коду std::error_code R>а иначе какой смысл в том что вы делаете ?
Сравнение это легаси код, возможности менять его нет. Я просто привел здесь дистиллированный пример.
Почетный кавалер ордена Совка.
Re[3]: is_error_code_enum - error: specialization after instantiation
Здравствуйте, Patalog, Вы писали:
P>Я так понимаю проблема в том, что сравнение стало приводит к инстанцированию is_error_code_enum<status> до его специализации. Почему? В смысле почему приводит, а не почему до специализации.
... P>Т.е. я так понимал, что сравнение enum'а идет через встроенное сравнение как арифметического типа. Судя по всему это не так. Хотелось бы понять почему. Выглядит так, что есть нек. глобальный шаблонный оператор сравнения, который enable_if<is_error_code_enum<T>::value>. При этом если заменить std::min именно на ручное сравнение, напр.
ага, примерно так и есть. Этот дистилиянт сохраняет проблему, посмотри
namespace mystd
{
template<typename T>
struct myspec { static constexpr bool value = false; }; // std::is_error_code_enumstruct Some// std::error_code
{
template<typename T, bool = myspec<T>::value>//инстанцирование myspec<T>
Some(T) {}
};
void operator<(Some, Some);//инстанцирование конструктора Sometemplate<typename T>
constexpr const T& mymin(const T& a, const T& b) // std::min
{
return b < a ? b : a;// пробует void operator<(Some, Some);
}
}
//////////////////////////////////////////////////////////////////////////////////////////////enum class status
{
ok = 0, fail = 1
};
status get(status s1, status s2)
{
return mystd::mymin(s1, s2);
}
namespace mystd
{
template <>
struct myspec<status> {static constexpr bool value = true; };
}
int main()
{
return 0;
}
Re[4]: is_error_code_enum - error: specialization after instantiation
Здравствуйте, Patalog, Вы писали:
P>Т.е. в сухом остатке это бага компилятора, а не ошибка в коде, праильно?
Не уверен на 100%, возможно, сейчас набегут gcc-шники и объяснят что это вовсе не бага а фича
P>Есть варианты обкостылить, кроме как убрать специализацию P>
P>struct is_error_code_enum<status>
P>
P>?
сложно говорить по такому минимализированному кусочку, не понятно что можно менять а что нет. Навскидку,
можно убрать специализацию
можно отказаться от использования std::min, тогда operator< не будет искаться в std и не будет активироваться проблемный
можно переместить специализацию ближе к определению status, чтобы между ними не вклинивалось использование operator<
можно сделать get шаблонным, тогда он будет инстанцироваться к конце единицы трансляции, то есть, не между объявлением status и специализацией
наверняка еще варианты есть
Re[8]: is_error_code_enum - error: specialization after instantiation
Это понятно.
V>можно отказаться от использования std::min, тогда operator< не будет искаться в std и не будет активироваться проблемный
Возможно это получится сделать в некоторых местах, но везде — однозначно нет.
V>можно переместить специализацию ближе к определению status, чтобы между ними не вклинивалось использование operator<
Не вариант, сам status в закрытом для такого рода изменений файле, то, куда и как он включается проконтролировать тоже не получится.
V>можно сделать get шаблонным, тогда он будет инстанцироваться к конце единицы трансляции, то есть, не между объявлением status и специализацией
Это примерно тоже самое что отказаться от std::min. Данный конкретный get я допустим поменяю, но все места где может что-то такое появится — нет.
V>наверняка еще варианты есть
Почетный кавалер ордена Совка.
Re[9]: is_error_code_enum - error: specialization after instantiation
Здравствуйте, Patalog, Вы писали: V>>наверняка еще варианты есть P>
можно подcунуть свою перегрузку std::min и внутри нее как нибудь по хитрому организовать сравнение, чтобы std-шные операторы сравнения не увидели status, примерно так
Скрытый текст
#include <system_error>
#define FAIL
enum class status
{
ok = 0, fail = 1
};
namespace std
{
constexpr status min(status a, status b)
{
return static_cast<int>(a) < static_cast<int>(b) ?
a :
b;
}
}
inline
status get(status s1, status s2)
{
return
#if defined(FAIL)
std::min(s1, s2);
#else
s1;
#endif
}
namespace std
{
template <>
struct is_error_code_enum<status>
: true_type
{};
}
int main()
{
get(status{}, status{});
return 0;
}