Paul Ivanov
Paul Ivanov

Reputation: 13

Selecting container type at compile time

I want to select one of the standard containers with one template parameter at compile time. Something like

    template<typename T>
    void foo()
    {
        using Container = std::conditional_t< std::is_same_v<T, int>, 
                std::vector, // T is int
                std::set>;    // any other T
        Container<T> bar;
    }

How to do this properly?

Upvotes: 0

Views: 464

Answers (3)

Marek R
Marek R

Reputation: 37607

Solution with std::conditional_t might be OK (and it was fixed in other answer), but IMHO it is better here use something more primitive: simple old fashioned template specialization:

template<typename T>
void foo()
{
    using Container = std::set<T>;
    Container<T> bar;
    someCode(bar);
}

template<>
void foo<int>()
{
    using Container = std::vector<T>;
    Container<T> bar;
    someOtherCode(bar);
}

Upvotes: 3

n. m. could be an AI
n. m. could be an AI

Reputation: 119847

The simplest way seems to be

using Container = std::conditional_t< std::is_same_v<T, int>, 
            std::vector<T>, // T is int
            std::set<T>>;
Container bar;

std::conditional_t allows you to select a type. There is no standard conditional template that would allow to select a template. You can write one if you want but this won't be convenient to use.

template <bool t, template <typename...> typename X, template <typename...> typename Y>
struct conditional_template;

template <template <typename...> typename X, template <typename...> typename Y>
struct conditional_template<true, X, Y>
{
    template <typename... ts> using type = X<ts...>;
};

template <template <typename...> typename X, template <typename...> typename Y>
struct conditional_template<false, X, Y>
{
    template <typename... ts> using type = Y<ts...>;
};

template <typename... ts>
using Container = conditional_template<true, std::list, std::vector>::type<ts...>;

Container<int> x;

It doesn't seem possible to define an analogue of std::conditional_t convenience alias.

Upvotes: 1

florestan
florestan

Reputation: 4655

Without knowing exactly what "properly" means in your question, what you probably want is the following:

template<typename T>
void foo()
{
    using Container = std::conditional_t< 
            std::is_same<T, int>::value,
            std::vector<T>, // T is int
            std::set<T>>;    // any other T
    Container bar;
}

Your original code did not work, because

  • std::conditional_t needs types as 2nd and 3rd parameters, but you spcified class templates instead.
  • There is no std::is_same_v in C++14, it arrived in C++17. You need to use std::is_same<X,Y>::value instead.

Full code here.

Upvotes: 0

Related Questions