Инициализировать целочисленный литерал в std:: size_t
Известны способы манипулирования типом целочисленного литерала
0L; // long
3U; // unsigned integer
1LL; // long long
Мне нужен способ инициализации целочисленного литерала до std::size_t
. Я предположил, что делать
2U; // unsigned int
будет достаточно, но я до сих пор получаю ошибку компилятора при вызове шаблона функции, который ожидает два аргумента одного и того же типа интегралов (никакой функции соответствия для вызова func(unsigned int, size_t
)
Я знаю/проверял, что явное кастинг (static_cast<std::size_t>(1)
) первый аргумент решает проблему, но я спрашиваю, есть ли более красивое решение
ИЗМЕНИТЬ
функция имеет сигнатуру
template <class T> const T& func(const T& a, const T& b);
EDIT2
Я не знаю, должен ли этот вопрос "винить", но я рад объявить, что это будет готов (cudos @malat для упоминания об этом в комментариях)
Ответы
Ответ 1
Нет такого стандартного средства. C99 и С++ 11 имеют такие макросы в <stdint.h>
/<cstdint>
. Но даже там макросы определяются только для типов stdint.h
, которые не включают size_t
.
Вы могли определить пользовательский литерал-оператор:
constexpr std::size_t operator "" _z ( unsigned long long n )
{ return n; }
auto sz = 5_z;
static_assert( std::is_same< decltype( sz ), std::size_t >::value, "" );
constexpr
необходимо использовать его в границах массива int arr[ 23_z ]
или case 9_z:
.
Большинство из них, вероятно, считают отсутствие макросов преимуществом:).
Отрезок в сторону, лучший способ - использовать инициализацию скобки: std::size_t{ 42 }
. Это не эквивалентно std::size_t( 42 )
, который похож на неприятный листинг C - предположительно, чего вы избегали с помощью static_cast
. Непосредственно: в фигурных скобках требуется, чтобы значение внутри точно представлялось в целевом типе. Итак, char{ 300 }
и std::size_t{ -1 }
оба плохо сформированы.
Скобки и parens выглядят одинаково, но они являются полярными противоположностями в безопасности при инициализации временных рядов. Скобки более безопасны, чем мог бы быть буквальный оператор, поскольку в отличие от функции они могут различать значения времени компиляции.
Ответ 2
Для std::size_t
нет выделенного суффикса. В С++ 11 вы можете создать для него литерал, определенный пользователем:
std::size_t operator "" _sz (unsigned long long int x)
{
return x;
}
// Usage:
auto s = 1024_sz;
static_assert(std::is_same<decltype(s), std::size_t>::value, "He wrong");
Живой пример
Ответ 3
В зависимости от функции вы также можете сделать это и можете найти его более чистым:
auto result = func<size_t>(1, some_var);
Например, я сделал это с помощью std::max
:
auto result = std::max<size_t>(0, std::min<size_t>(index, vec.size()-1));
Явным образом указывая экземпляр шаблона, приведения может быть неявным. Однако, обратите внимание, что это листинг, поэтому он восприимчив к ошибкам, которые инициализация скобок Potatoswatter не является.