Какова цель std :: to_integer? - PullRequest
8 голосов
/ 23 июня 2019

Насколько я знаю, std::to_integer<T> эквивалентно T(value), где value - это переменная, имеющая тип std::byte.
Я рассмотрел некоторые реализации основных компиляторов и обнаружил, что в этом случае эквивалент означает буквально , реализованный как .Другими словами, в большинстве случаев to_integer фактически реализуется как:

return T(value);

И это все.

Что я не понимаю, какова цель такой функции?
По иронии судьбы минусы даже больше, чем плюсы.Я должен включить целый заголовок для такой функции, чтобы избежать C-подобного приведения, который, скорее всего, в любом случае будет напрямую встроен.

Есть ли какая-либо другая причина для этого, или это просто хорошо выглядящий альтернатива для C-подобного броска и ничего более?

Ответы [ 4 ]

11 голосов
/ 23 июня 2019

это просто действительно симпатичная альтернатива для C-подобного броска и ничего более?

Вы говорите, как будто это какая-то тривиальная деталь.

Приведенияопасно.Легко привести что-то к неправильному типу, и часто компиляторы не будут мешать вам делать именно это.Кроме того, поскольку std::byte не является целочисленным типом в C ++, работа с числовыми значениями байтов часто требует определенного количества приведений.Наличие функции, которая явно преобразует в целые числа, делает работу с пользователем более безопасной.

Например, float(some_byte) совершенно допустимо, а to_integer<float>(some_byte) явно запрещено.to_integer<T> требует, чтобы T был целым типом.

to_integer является более безопасной альтернативой.

Я должен включить целый заголовок для такогофункция

Если под "целым заголовком" подразумевается тот же заголовок , от которого вы получили std::byte и, следовательно, уже по определению включен ...

9 голосов
/ 23 июня 2019

std::to_integer<T>(some_byte) эквивалентно T(some_byte) , если оно действительно компилируется .T(some_byte) эквивалентно небезопасному броску в стиле C (T)some_byte, который может делать страшные вещи .С другой стороны, std::to_integer соответствующим образом ограничен для работы только тогда, когда это безопасно:

Эта перегрузка участвует только в разрешении перегрузки, если std::is_integral_v<IntegerType> имеет значение true.

Если T на самом деле не был целочисленным типом, а не иметь потенциально неопределенное поведение, код не будет компилироваться.Если some_byte на самом деле не является std::byte, а не потенциально неопределенным поведением, код не будет компилироваться.

3 голосов
/ 23 июня 2019

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

2 голосов
/ 23 июня 2019

Приведение в стиле AC не эквивалентно std::to_integer<T>.Смотрите пример ниже.

std::to_integer<T> участвует только в разрешении перегрузки, если std::is_integral_v<T> имеет значение true.

#include <cstddef>
#include <iostream>

template <typename T>
auto only_return_int_type_foo(std::byte& b)
{
    return std::to_integer<T>(b);
}

template <typename T>
auto only_return_int_type_bar(std::byte& b)
{
    return T(b);
}

int main()
{
    std::byte test{64};
    // compiles
    std::cout << only_return_int_type_foo<int>(test) << std::endl;

    // compiler error
    std::cout << only_return_int_type_foo<float>(test) << std::endl;

    // compiles
    std::cout << only_return_int_type_bar<int>(test) << std::endl;

    // compiles
    std::cout << only_return_int_type_bar<float>(test) << std::endl;
} 
...