hgiesel
hgiesel

Reputation: 5648

STL container template parameter containing certain object

I have a function f:

template <typename T>
void f(T<int> ints)
{ /* */ }

This function is supposed to take std::vector<int> or std::initializer_list<int> or any other STL container, but only, if it contains int.

I can live with it accepting other classes with int as a template parameter, but I don't want it to accept std::vector<char> or std::vector<double> or std::list<double> or something like this.

How can I realize this?

Upvotes: 1

Views: 111

Answers (2)

Maxim Egorushkin
Maxim Egorushkin

Reputation: 136256

Pedantically, that is a function template from which a function is instantiated.

One solution is to detect value_type which standard containers provide:

template<class T>
typename std::enable_if<std::is_same<int, typename T::value_type>::value>::type
void f(T const& ints);

That will not work with built-in arrays though, as they do not have embedded value_type. For built-in arrays you can add an overload:

template<size_t N>
void f(int const(&ints)[N]);

Upvotes: 1

TartanLlama
TartanLlama

Reputation: 65620

You could use a template template parameter:

template <template <typename...> typename T>
void f(const T<int>& ints)
{ /* */ }

But I would recommend using the value_type type member of containers instead. This will avoid matching other templates with int as the template parameter.

//using std::enable_if_t
template <typename T>
std::enable_if_t<std::is_same<typename T::value_type, int>::value> 
f(const T& ints)
{ /* */ }

//or static_assert
template <typename T>
void f(const T& ints) { 
    static_assert(std::is_same<typename T::value_type, int>::value,
                  "T must be a container of ints"); 
    //...
}

Upvotes: 5

Related Questions