Я вижу два возможных стиля для реализации списков типов в С++ 11/14, и мне было любопытно, есть ли какие-либо причины предпочесть друг другу. Первый метод изложен здесь и моделирует себя в библиотеке Boost MPL. В этом стиле вы определяете мета-свободные функции (верхний уровень с использованием объявлений), которые принимают списки типов и работают на них. Вот как вы бы реализовали мета-версию std:: transform, которая работает с типами вместо значений в первом стиле:
template <typename... Args>
struct type_list;
namespace impl
{
template <template <typename...> class F, class L>
struct transform_impl;
template <template <typename...> class F, template <typename...> class L, typename... T>
struct transform_impl<F, L<T...>>
{
using type = L<typename F<T>::type...>;
};
}
template <template <typename...> class F, class L>
using transform = typename impl::transform_impl<F, L>::type;
Второй стиль - это определить мета-методы (используя объявления внутри структуры списка типов). Вот как выглядит преобразование в этом стиле:
template <typename... Args>
struct type_list {
// ... other 'methods'
template<template<class> class Wrapper>
using transform =
type_list<Wrapper<Args>...>;
// ... other 'methods'
};
Преимущество, которое я вижу во втором стиле, состоит в том, что у вас все еще есть пакет параметров Args...
, поэтому вам не нужно делегировать вспомогательные функции impl
. Два возможных недостатка: 1) вы должны поместить все свои мета-функции внутри type_list, а не помещать их в отдельные заголовки, поэтому вы теряете модульность и 2) мета-функции "free" также будут работать с кортежами и любым другим вариационным шаблоном класс из коробки. Я не знаю, насколько обычным является желание на # 2 на практике, я только нашел случаи, когда я использую type_list и кортеж сам, и писать мета-код для перевода между type_list и кортежем не так уж сложно.
Есть ли веская причина сильно предпочесть тот или иной? Может быть, # 2 - это обычный случай?