Все аргументы шаблона имеют одинаковый тип. [...] возможно ли это в C ++ 17?
Да, это возможно.
Но не так просто и с некоторыми недостатками.
Вы можете написать конструктор, принимающий аргументы другого типа; это просто
template <typename ... Ts>
Alfa (const Ts & ... as)
{ std::tuple<Ts...> data{as...}; }
, но это позволяет различать типы Ts...
.
Вы можете навязать, что все типы одинаковы, используя SFINAE, следующим образом
template <typename T, typename ... Ts,
std::enable_if_t<(std::is_same_v<T, Ts> && ...), bool> = true>
Alfa (T const & a0, Ts const & ... as)
{
std::tuple<T, Ts...> data0{a0, as...};
std::array data1{a0, as...};
}
, поэтому ваш конструктор включен, только если все типы Ts...
, следующие за первым T
, в точности совпадают с T
Недостаток: работает с
Alfa alfa{1, 2, 3, 4};
но выдает ошибку с
Alfa alfa{1l, 2l, 3, 4l}; <-- 3 isn't long
, потому что 3
конвертируется в long
(1l
- long
), но не long
.
Так что вы можно проверить, можно ли преобразовать следующие Ts...
в T
; вместо этого они равны
template <typename T, typename ... Ts,
std::enable_if_t<(std::is_convertible_v<Ts, T> && ...), bool> = true>
Alfa (T const & a0, Ts const & ... as)
{
std::tuple<T, Ts...> data0{a0, as...};
std::array<T, sizeof...(Ts)+1u> data1{a0, as...};
}
, но таким образом вы придаете T
большее значение для других типов (работает, если все * 1042) * могут быть преобразованы в T
, но не в случае, если T
может быть преобразовано в один из Ts...
), поэтому я полагаю, что лучшим решением является проверка, существует ли общий тип
template <typename ... Ts,
typename CT = std::common_type_t<Ts...>>
Alfa (Ts const & ... as)
{
std::tuple<Ts...> data0{as...};
std::array<CT, sizeof...(Ts)> data1{as...};
}