I give the following codes to show my question:
template<T>
void my_fun(T &obj)
{
if(obj is a type like float, std::string, double)
{
perform1()
}
if(obj is a container like std::vector, std::list)
{
perform2()
}
}
std::vector<int> abc;
my_fun(abc);
int d;
my_fun(d);
Then my questions, how can I know the template refers to a simple type or a container? Thanks.
1) std::vector is a sequence container that encapsulates dynamic size arrays.
std::list is a container that supports constant time insertion and removal of elements from anywhere in the container. Fast random access is not supported. It is usually implemented as a doubly-linked list.
The string class is not part of the STL, but has implemented many STL features. string can be treated as a STL container of char .
You can write your own trait and enable_if
on it via expression SFINAE with multiple overloads. Here is a solution that uses the void_t
trick (which will presumably appear in C++17):
#include <iostream>
#include <type_traits>
#include <vector>
template<typename ...>
using to_void = void; // maps everything to void, used in non-evaluated contexts
template<typename T, typename = void>
struct is_container : std::false_type
{};
template<typename T>
struct is_container<T,
to_void<decltype(std::declval<T>().begin()),
decltype(std::declval<T>().end()),
typename T::value_type
>> : std::true_type // will be enabled for iterable objects
{};
template<typename T>
void f(T param, typename std::enable_if<is_container<T>::value>::type* = nullptr)
{
std::cout << "Container\n";
}
template<typename T>
void f(T param, typename std::enable_if<std::is_fundamental<T>::value>::type* = nullptr)
{
std::cout << "Fundamental\n";
}
template<typename T>
void f(T param,
typename std::enable_if<!std::is_fundamental<T>::value>::type* = nullptr,
typename std::enable_if<!is_container<T>::value>::type* = nullptr)
{
std::cout << "Other\n";
}
struct Foo{};
int main()
{
int x{}; // fundamental
std::vector<int> v; // container
Foo s{}; // other
f(x);
f(v);
f(s);
}
Live on Coliru
You have several options at your disposal.
For example :
template<typename T>
void myfunc() { /*default*/ }
template<>
void myfunc<int>() { /*specialized version for int */}
std::is_fundamental
). You might have to implement your own type traits in thiscase.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