#c #templates #c 17 #parameter-pack
#c #шаблоны #c 17 #parameter-pack
Вопрос:
Учитывая следующее, как я могу правильно создать объект неизвестного типа из пакета параметров?
template < typename... Types >
auto foo( Typesamp;amp;... types ) {
auto result = Types{ }; // How should this be done?
// Do stuff with result
return resu<
}
Я ожидаю, что функция шаблона будет вызываться только с соответствующими типами, поэтому все в пакете параметров должно быть одного типа. Не имеет значения, на какой отдельный элемент я ссылаюсь, если мне нужно использовать decltype
, например (соответствующий код в разделе с комментариями в противном случае вызовет ошибки компиляции).
Комментарии:
1. И если пакет параметров пуст, какой объект вы ожидаете создать? An
int
? Abool
?. И если для функции требуется хотя бы один параметр, просто объявите функцию с одним параметром шаблона и, возможно, пустым пакетом параметров и просто используйте тип первого параметра напрямую.2. @SamVarshavchik простое исправление
static_assert( sizeof...( pack ) > 1 );
. Также я рассматривал эту возможность, но давайте пока проигнорируем ее и просто ответим на вопрос как есть. Предположим, что он используется в другом сценарии.
Ответ №1:
Поскольку все типы в пакете параметров одинаковы, вы можете сначала использовать оператор запятой для расширения пакета параметров, а затем использовать decltype
для получения типа последнего операнда.
template<typename... Types>
auto foo(Typesamp;amp;... types) {
auto result = decltype((Types{}, ...)){ };
// Do stuff with result
return resu<
}
Ответ №2:
Вот один из способов (предполагая, что мы говорим об относительно простых типах, которые могут выдерживать копирование):
template < typename... Types >
auto foo( Typesamp;amp;... types ) {
return std::array{types...}[0];
}
Вот другой, более сложный, но работающий способ, который не накладывает дополнительных ограничений на типы:
#include <tuple>
template < typename... Types >
auto foo( Typesamp;amp;... types ) {
using tup_t = std::tuple<Types...>;
auto result = std::tuple_element_t<0, tup_t>{};
// Do stuff with result
return resu<
}
// auto k = foo(); // compile error
auto z = foo(10); // z is 0-initialized int
Комментарии:
1. Интересная работа, возможно, придется пойти на это, если никто другой не предложит более прямое решение. Спасибо!
2. @cbrng добавил еще один
Ответ №3:
Поскольку все типы в пакете параметров одинаковы, вы можете использовать std::common_type_t , который дает тип, в который могут быть преобразованы все типы в пакете параметров.
template <typename... Types>
auto foo(Typesamp;amp;... types) {
auto result = std::common_type_t<Types...>{};
// Do stuff with result
return resu<
}