Может ли руководство по выводу шаблона вызывать функции constexpr?
У меня есть свой собственный тип массива с фиксированным размером, который я хочу, чтобы constexpr
можно было constexpr
из std::initializer_list
без необходимости явно определять аргумент шаблона размера.
Я думал, что смогу использовать руководство по выводу шаблона, но похоже, что он не рассматривает std::initializer_list::size()
как функцию constexpr для него.
Вот пример попытки сделать руководство по std::array
для std::array
(который похож на мой тип и имеет ту же проблему):
namespace std
{
template<typename T> array(initializer_list<T> initialiserList) -> array<T, initialiserList.size()>;
}
static constexpr std::array myArray = {1,2,3};
static constexpr std::array myArray2 = {{1,2,3}};
Я пробовал на MSVC и Clang, оба дают примерно одинаковые ошибки: myArray
имеет ошибку, из-за которой слишком много аргументов для функции. myArray2
говорит: "ошибка замещения [с T = int]: аргумент шаблона не-типа не является константным выражением"
Я попытался поместить constexpr
перед руководством по constexpr
или аргументом функции, но ни один из них, по-видимому, недопустим, поэтому кажется, что руководство по constexpr
является недействительным, даже если оно отлично работает в контексте constexpr
.
Есть ли способ сделать это без перехода по маршруту make_array()
?
Ответы
Ответ 1
Ты можешь сделать:
template <class T, class... U>
array(T, U...) -> array<T, 1 + sizeof...(U)>;
Проблема не в том, что вы не можете вызывать функции constexpr
в руководствах по constexpr
. Вы можете. Этот пример смешной, но работает:
constexpr size_t plus_one(size_t i) { return i + 1; }
template <class T, class... U>
array(T, U...) -> array<T, plus_one(sizeof...(U))>;
Проблема в том, что параметры функции не constexpr
объектами constexpr
, поэтому вы не можете вызывать constexpr
члены constexpr
для них, если эти функции-члены читают вид локального состояния.
Ответ 2
Есть ли способ сделать это без перехода по маршруту make_array()
?
Почему бы вам не попробовать следующее руководство по выводу?
template <typename T, std::size_t N>
array(T const (&)[N]) -> array<T, N>;
Таким образом, аргумент в myArray2 = {{1,2,3}}
не интерпретируется как std::initializer_list
(который в качестве аргумента не может рассматриваться как constexpr
, поэтому его size()
нельзя использовать для шаблонный аргумент), но как массив в стиле C.
Таким образом, можно сделать вывод, что в качестве аргумента шаблона можно использовать аргументы шаблона, тип и размер (T
и N
), а также размер (N
).
Ответ 3
Значения параметра/аргумента не являются constexpr
.
Вы можете использовать шаблон переменной для определения размера во время компиляции или вводить с известным размером (ссылка на std::array
или C-array).