dodomorandi
dodomorandi

Reputation: 1153

Declare "container" object from templated template class and variadic templates

I need to declare a class which could store different kind of containers. i.e. It would be nice if it could handle std::bitset and std::array. However, these two classes need a different of template arguments... Is it possible (and possibly, how) to use templated template classes and variadic templates to declare this kind of class?

Example (but wrong):

template<template <typename..., std::size_t> class Container,
         std::size_t N,
         typename... Args>
class Base_Class
{
    ...
    Container<Args..., N/2> container;
};

The compiler complains that N/2 is not a type. Obviously, for both std::array and std::bitset I need the size to be the last template parameter... Is it possible to code this crazyness?

Thank you!

EDIT: As far as I am concerned, the main problem is that variadic templates can only be expanded on the right, therefore the variadic parameter must be the last one. Anyone know if there are any plans to allow the following syntax in C++17?

template<typename... Args, typename T>
struct A
{};

Upvotes: 5

Views: 461

Answers (2)

Walter
Walter

Reputation: 45434

Anton's answer can be made somewhat less container-specific by using template template parameters for the speciliasations of ResizedContainer:

namespace detail {
    template<typename Container>
    struct ResizedContainer;

    template<template<typename,std::size_t> class Container,
             typename T, std::size_t N>
    struct ResizedContainer<Container<T,N>> {
        using type = Container<T,N/2>;
    };

    template<template<std::size_t> class Container,
             std::size_t N>
    struct ResizedContainer<Container<N>> {
        using type = Container<N/2>;
    };
}

#include <array>
#include <bitset>

template<typename Container>
class Base_Class {
    typename detail::ResizedContainer<Container>::type container;
};

int main() {
    Base_Class<std::array<int,4>> a;
    Base_Class<std::bitset<5>> b;
}

Upvotes: 3

Anton Savin
Anton Savin

Reputation: 41301

Maybe something like this:

namespace detail {
    template<typename Container>
    struct ResizedContainer;

    template<typename T, size_t N>
    struct ResizedContainer<std::array<T, N>> {
        using type = std::array<T, N/2>;
    };

    template<size_t N>
    struct ResizedContainer<std::bitset<N>> {
        using type = std::bitset<N/2>;
    };
}

template<typename Container>
class Base_Class {
    typename detail::ResizedContainer<Container>::type container;
};

int main() {
    Base_Class<std::array<int, 4>> a;
    Base_Class<std::bitset<5>> b;
}

Upvotes: 2

Related Questions