enum class value initialization
От: B0FEE664  
Дата: 26.02.22 12:53
Оценка: 2 (1)
Решил я сегодня первый раз воспользоваться функцией std::from_chars и не понял как правильно проверять результат вызова.
Дело в том, что в случае успеха "ec is value-initialized", где ec это поле from_chars_result:
struct from_chars_result {
    const char* ptr;
    std::errc ec;
};

При этом std::errc определяется в стандарте как
enum class errc {
address_family_not_supported, // EAFNOSUPPORT
....

При этом в MS компиляторе определение такое:
    // ENUM CLASS errc
enum class errc
    {    // names for generic error codes
    address_family_not_supported = 102, // EAFNOSUPPORT
...


Если я правильно понимаю, "ec is value-initialized" означает инициализацию вида errc{}.
Внимание вопрос: какое значение будет у ec в случае успешного выполнения?
Я вижу возможные варианты:
1) unspecified
2) undefined behavior
3) 0
4) errc::address_family_not_supported

Так как у errc не указан underlying type, то если я правильно помню, присваивание любого значения лежащего вне перечисленных — это undefined behavior. Это так? Если так, то либо у address_family_not_supported == 0, либо errc{} != 0.

Короче: с чем, согласно стандарту, следует сравнивать значение std::errc{} ?
И каждый день — без права на ошибку...
Re: enum class value initialization
От: Igore Россия  
Дата: 26.02.22 18:05
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Решил я сегодня первый раз воспользоваться функцией std::from_chars и не понял как правильно проверять результат вызова.

BFE>Если я правильно понимаю, "ec is value-initialized" означает инициализацию вида errc{}.
BFE>Внимание вопрос: какое значение будет у ec в случае успешного выполнения?
Чем первая строка из примера документации не нравится?
        if (ec == std::errc())
        {
            std::cout << "Result: " << result << ", ptr -> " << std::quoted(ptr) << '\n';
        }
Re[2]: enum class value initialization
От: B0FEE664  
Дата: 26.02.22 20:01
Оценка:
Здравствуйте, Igore, Вы писали:

BFE>>Решил я сегодня первый раз воспользоваться функцией std::from_chars и не понял как правильно проверять результат вызова.

BFE>>Если я правильно понимаю, "ec is value-initialized" означает инициализацию вида errc{}.
BFE>>Внимание вопрос: какое значение будет у ec в случае успешного выполнения?
I>Чем первая строка из примера документации не нравится?
I>
I>        if (ec == std::errc())
I>        {
I>            std::cout << "Result: " << result << ", ptr -> " << std::quoted(ptr) << '\n';
I>        }
I>

Ничем не нравится:
Откуда следует, то это не undefined behavior?
Какое значение у std::errc()?
Откуда следует, что оно не совпадает ни с каким значение ошибки?

Относительно undefined behavior:
Если посмотреть в дебагере, то у std::errc() значение 0, но этого значения нет в перечислении. При этом:

If the enumeration type does not have a fixed underlyingtype, the value is unchanged if the original value is within the range of the enumeration values (9.7.1), and otherwise, the behavior is undefined.

это из 7.6.1.8/10 С++17

Мне не понятно, что такое the range of the enumeration values. У него крайне смутное описание:
9.7.1/8

For an enumeration whose underlying type is fixed, the values of the enumeration are the values of the underlying type. Otherwise, the values of the enumeration are the values representable by a hypothetical integer type with minimal width M such that all enumerators can be represented. The width of the smallest bit-field large enough to hold all the values of the enumeration type is M. It is possible to define an enumeration that has values not defined by any of its enumerators. If the enumerator-list is empty, the values of the enumeration are as if the enumeration had a single enumerator with value 0.


Мне совсем не сложно представить гипотетический целый тип состоящий из двух бит и принимающий значения (3,4,5,6) для перечисления enum class X{ a=3, b=4, c=5, d=6 }; Нуля среди них нет, значит 0 — вне диапазона. Или же где-то сказано, про какие-то ограничения на гипотетические целые типы?
Ладно, предположим, что 0 всегда допустимое значение для перечисления (хотя я пока не вижу откуда это следует), тогда откуда можно узнать, errc{} не совпадает ни с каким значением этого перечисления?
И каждый день — без права на ошибку...
Re: enum class value initialization
От: Zhendos  
Дата: 26.02.22 20:20
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Если я правильно понимаю, "ec is value-initialized" означает инициализацию вида errc{}.

BFE>Внимание вопрос: какое значение будет у ec в случае успешного выполнения?
BFE>Я вижу возможные варианты:
BFE>1) unspecified
BFE>2) undefined behavior
BFE>3) 0
BFE>4) errc::address_family_not_supported

Я думаю (3):
https://stackoverflow.com/questions/53897991/enum-class-default-initialization

Как описанно по ссылки auto x = errc() эквиванетно auto x = static_cast<errc>(0).

BFE>Так как у errc не указан underlying type, то если я правильно помню, присваивание любого значения лежащего вне перечисленных — это undefined behavior. Это так? Если так, то либо у address_family_not_supported == 0, либо errc{} != 0.


По идее только если значение не может уместиться в "underlying type" то это UB, а 0 всегда может уместиться
в "underlying type":

https://stackoverflow.com/questions/33812998/is-it-allowed-for-an-enum-to-have-an-unlisted-value

см. последний комментарий.
Отредактировано 26.02.2022 20:21 Zhendos . Предыдущая версия .
Re[3]: enum class value initialization
От: johny5 Новая Зеландия
Дата: 11.04.22 11:57
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Мне совсем не сложно представить гипотетический целый тип состоящий из двух бит и принимающий значения (3,4,5,6) для перечисления [tt]enum class X..


Вопрос теоретически интересный, но думаю в стандарте не углублялись, опираясь на "очевидные" легаси понимания как enum в железе представляется. В конце концов никто static_cast<int>() / std::to_underlying не отменил и enum class тут дела не изменил, только добавил namespace сахарку. Значение в underlying type должно быть равным значению поля enum-а.

По мне действительно выглядит недоделкой в стандарте, им бы по хорошему ввести NoError значение. Но, это при большом желании, нужно писать им прямо туда.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.