Подтвердить что ты не робот

Инициализировать целочисленный литерал в 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 для упоминания об этом в комментариях)

4b9b3361

Ответ 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 не является.