Ответ 1
template<int ...>
const std::vector<int>*make_from_ints(int args...)
{ return new std::vector<int>(std::initializer_list<int>{args}); }
В приведенном выше фрагменте есть множество проблем:
-
Возврат
const std::vector<int>*
вместоstd::vector<int>
и без необходимости использования динамического выделения.- Даже если вы хотите использовать динамическое распределение, вы должны использовать
std::make_unique
вместоnew
.
- Даже если вы хотите использовать динамическое распределение, вы должны использовать
-
Вы определили
make_from_ints
как функцию шаблона, которая принимает любое количество параметров шаблонаint
, но вы не даете этимint
имя - вы никогда не сможете их использовать! -
Ваша подпись фактически анализируется как
make_from_ints(int args, ...)
- это подпись Cva_args
, которая не имеет никакого отношения к вариационным шаблонам.- Правильный синтаксис для пакета аргументов -
type... name
.
- Правильный синтаксис для пакета аргументов -
Если вы хотите принять любое количество аргументов определенного типа, которое хорошо работает с выводом аргумента шаблона, самый простой способ - использовать обычный вариационный шаблон, который принимает произвольное количество типов и static_assert
их тип (или использует std::enable_if
для удобства SFINAE). Вот пример:
template <typename... Ts>
auto make_from_ints(Ts... xs)
{
static_assert((std::is_same<Ts, int>::value && ...));
return std::vector<int>{xs...};
}
template <typename... Ts>
auto make_from_doubles(Ts... xs)
{
static_assert((std::is_same<Ts, double>::value && ...));
return std::vector<double>{xs...};
}
Использование:
for(auto x : make_from_ints(1,2,3,4)) std::cout << x << " ";
std::cout << "\n";
for(auto x : make_from_doubles(1.0,1.5,2.0,2.5)) std::cout << x << " ";
1 2 3 4
1 1,5 2 2,5
Обратите внимание, что я использую С++ 17-кратное выражение, чтобы проверить, являются ли все Ts...
здесь определенного типа:
static_assert((std::is_same<Ts, int>::value && ...));
Если у вас нет доступа к функциям С++ 17, это можно легко заменить чем-то вроде:
template <typename... Ts>
constexpr auto all_true(Ts... xs)
{
for(auto x : std::initializer_list<bool>{xs...})
if(!x) return false;
return true;
}
// ...
static_assert(all_true(std::is_same<Ts, int>{}...));