Может ли руководство по выводу шаблона вызывать функции constexpr? - PullRequest
0 голосов
/ 07 января 2019

У меня есть свой собственный тип массива фиксированного размера, я хочу быть constexpr конструируемым из std::initializer_list без необходимости явно определять аргумент шаблона размера.

Я думал, что смогу использовать руководство по выводу шаблона, но похоже, что он не рассматривает std::initializer_list::size() как функцию constexpr для него.

Вот пример попытки сделать руководство по выводу для 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.

Есть ли способ заставить эту работу не идти по маршруту make_array()?

Ответы [ 3 ]

0 голосов
/ 07 января 2019

Есть ли способ заставить эту работу не идти по маршруту 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) могут быть использованы в качестве аргумента шаблона.

0 голосов
/ 07 января 2019

Вы можете сделать:

template <class T, class... U>
array(T, U...) -> array<T, 1 + sizeof...(U)>;

Проблема не в том, что вы не можете вызвать 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 функции-члены для них, если эти функции-члены читают вид локального состояния.

0 голосов
/ 07 января 2019

Значения параметра / аргумента не constexpr.

Вы можете использовать шаблон переменной для определения размера во время компиляции или вводить с известным размером (std::array или ссылка на массив C).

...