I am looking for a way to provide a function that takes a templated (STL) container, but requires its elements to be of a certain type (e.g. int
).
These function calls should be VALID:
std::vector<int> Argument;
void foo( Argument );
std::list<int> Argument
void foo( Argument );
std::deque<int> Argument
void foo( Argument );
...etc
These function calls should be INVALID:
std::vector<float> Argument;
void foo( Argument );
std::list<double> Argument
void foo( Argument );
std::deque<char> Argument
void foo( Argument );
...etc
Is there a way to template "foo" such that containers of int
are accepted, but containers with different element types are not accepted ?
Best, Ben
Use the Standard Library semantics :
foo
, not a container : it makes your function much more genericstd::iterator_traits<Iterator>::value_type
to get to the value typestatic_assert
the value type of the Iterator to be an int
(or whatever type you want)Example :
#include <list>
#include <vector>
template<typename Iterator>
void foo(Iterator begin, Iterator end)
{
static_assert(std::is_same<int, typename std::iterator_traits<Iterator>::value_type>::value,
"Invalid value type : must be int");
}
int main() {
std::list<int> l1;
std::vector<int> v1;
foo(std::begin(l1), std::end(l1)); // OK
foo(std::begin(v1), std::end(v1)); // OK
std::vector<float> v2;
foo(std::begin(v2), std::end(v2)); // Doesn't compile
}
Live demo
Note:
foo
needs to access specific member functions of the container (as noted by Deduplicator, this might happen for performance reasons), then you might need to stick with the Container
argument :Example : (Note the difference for getting at the value_type
, as pointed by MooingDuck, this is required to make it work with arrays):
template <typename Container>
void foo(const Container& c)
{
static_assert(std::is_same<int, std::iterator_type<decltype(std::begin(c))>::value_type>::value, "Invalid value type : must be int");
// Use c member function(s)
}
STL containers have the typedef
value_type
, so you may use it.
Then you may forbid with static_assert
:
template <typename Container>
void foo(const Container& )
{
static_assert(std::is_same<int, typename Container::value_type>::value, "expect int type");
}
or via SFINAE
template <typename Container>
typename std::enable_if<std::is_same<int, typename Container::value_type>::value>::type
foo(const Container& )
{
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With