Специализация шаблона - это, вероятно, самый простой способ.
template <typename T>
struct functionize;
template <typename... Ts>
struct functionize<std::tuple<Ts...>> {
using type = std::tuple<std::function<void(Ts)>...>;
}
using MyTuple = std::tuple<int, double, char>;
using MyTupleFunctionized = typename functionize<MyTuple>::type;
Чтобы сделать его более обобщенным c, вы можете принять параметр шаблона шаблона для применения к пакету.
template <typename Tuple, template <typename> typename Component>
struct transform_tuple;
template <typename... Ts, template <typename> typename Component>
struct transform_tuple<std::tuple<Ts...>, Component> {
using type = std::tuple<Component<Ts>...>;
}
using MyTuple = std::tuple<int, double, char>;
using MyTransformedTuple = typename transform_tuple<MyTuple, std::shared_ptr>::type;
Более общее решение лучше всего работает с c++17
или более поздней версией. До этого он соответствовал бы только шаблону с ровно 1 параметром. После c++17
он также сможет сопоставляться с чем-то вроде std::vector
, у которого есть 2 параметра шаблона, где второй имеет аргумент по умолчанию.
Редактировать:
Как указано в комментариях @ Jarod42 и @Caleth мы можем улучшить это немного больше.
template <typename Tuple, template <typename...> typename Component>
struct transform_tuple;
Пакет параметров для параметра шаблона шаблона позволяет нам передавать что-то вроде std::vector
из c++11
и вперед. Это оставляет проблемы, только если мы хотим передать что-то, смешивающее типовые и нетиповые параметры, такие как std::array
.
Мы можем частично решить эту проблему, используя псевдонимы шаблонов.
template <typename T>
using FixedArray10 = std::array<T, 10>;
using MyTransformedTuple = typename transform_tuple<MyTuple, FixedArray10>::type;