Создание POD с переменным количеством элементов - PullRequest
4 голосов
/ 26 ноября 2010

Я хотел бы иметь тип, который будет в действительности POD, но я бы хотел иметь возможность указать, как и какие типы в нем, например:

template<Args...>
struct POD
{
//here I would like to create depending on Args appropriate types as a members.
};

Возможно ли это сделать с помощью этой новой функции шаблонов переменных в C ++ 0x?

Ответы [ 2 ]

0 голосов
/ 27 ноября 2010

Вы знакомы с std::tuple?

AFAIK, это POD, если все его участники - POD, если я ошибаюсь, я предполагаю, что это невозможно.

0 голосов
/ 26 ноября 2010

Я еще никогда не использовал функцию вариадических шаблонов C ++ 0x, но следующий код компилируется в G ++ 4.5:

template <typename... Args>
struct tuple;

template <typename T, typename... Args>
struct tuple<T, Args...> {
    T value;
    tuple<Args...> inner;
};

template <typename T>
struct tuple<T> {
    T value;
};

Однако их инициализация ... странная, потому что нам нужно nest внутренние значения:

int main() {
    tuple<int> n1 = { 23 };
    tuple<int, float> n2 = { 42, { 0.5f } };
    tuple<std::string, double, int> n3 = { "hello, world", { 3.14, { 97 } } };
}

Получение значений, конечно, немного утомительно.Простейший метод, вероятно, состоит в том, чтобы предоставить шаблон функции get<N>().

Но мы не можем напрямую реализовать get, поскольку шаблоны функций не могут быть частично специализированными.Либо нам нужно использовать SFINAE (читай: boost::enable_if), либо нам нужно делегировать фактическую функцию get типу, который может быть частично специализированным.

Далее я сделал последнее.Но сначала нам понадобится еще одна черта вспомогательного типа: nth_type, которая возвращает соответствующий тип возврата функции get:

template <unsigned N, typename... Args>
struct nth_type;

template <unsigned N, typename T, typename... Args>
struct nth_type<N, T, Args...> : nth_type<N - 1, Args...> { };

template <typename T, typename... Args>
struct nth_type<0, T, Args...> {
    typedef T type;
};

Easy-peasy.Просто возвращает n -ый тип в списке типов.

Теперь мы можем написать нашу get функцию:

template <unsigned N, typename... Args>
inline typename nth_type<N, Args...>::type get(tuple<Args...>& tup) {
    return get_t<N, Args...>::value(tup);
}

Как я уже сказал, это только делегатызадание.Нет, важная персона.На практике мы, вероятно, хотим иметь еще одну перегрузку для const кортежей (но тогда на практике мы будем использовать существующий тип tuple).

Теперь для убийства, за которым следует легкий салат:

template <unsigned N, typename... Args>
struct get_t;

template <unsigned N, typename T, typename... Args>
struct get_t<N, T, Args...> {
    static typename nth_type<N, T, Args...>::type value(tuple<T, Args...>& tup) {
        return get_t<N - 1, Args...>::value(tup.inner);
    }
};

template <typename T, typename... Args>
struct get_t<0, T, Args...> {
    static T value(tuple<T, Args...>& tup) {
        return tup.value;
    }
};

И все.Мы можем проверить это, напечатав некоторые значения в наших ранее определенных переменных:

std::cout << get<0>(n1) << std::endl; // 23
std::cout << get<0>(n2) << std::endl; // 42
std::cout << get<0>(n3) << std::endl; // hello, world

std::cout << get<1>(n2) << std::endl; // 0.5
std::cout << get<1>(n3) << std::endl; // 3.14

std::cout << get<2>(n3) << std::endl; // 97

Человек, это забавно возиться с вариадическими шаблонами.

...