The standard library and the three enablers of boost_ If series of functions can help us overload template functions.
Overloading of general functions
Let's take a look at an example of general function overloading:
#include <iostream> void print(int i) { std::cout << "Integral: " << i << std::endl; } void print(double f) { std::cout << "Floating point: " << f << std::endl; } int main() { print(42); print(3.14); }
above code It is an overload of a general function. The program will match according to the parameter type of the function and execute the corresponding function.
However, if the print above is a class template function, can it implement similar functions, such as:
template <typename T> void print(T f) { std::cout << "Floating point: " << f << std::endl; }
When type T is double, call the function corresponding to the above parameter 3.14. When type T is int, call the function corresponding to the above parameter 42. Obviously, if the above parameters are uniformly replaced with T, take int and double as examples:
template <typename T> void print(T f) { std::cout << "Floating point: " << f << std::endl; } template <typename T> void print(T f) { std::cout << "Integral: " << i << std::endl; }
The compiler will prompt: redefinition of 'template void print(T)
Then, is there a way to generate code of the corresponding type only when the template parameter is a certain type. std::enable_if and boost are designed to help implement similar functions.
std::enable_ Role of if
First look at std::enable_if definition:
std::enable_if itself is a template function with two template parameters. The first is a bool type non type parameter, and the second is the type parameter T. when the bool value is true, std::enable_if defines a typedef type of public type, which is the same as T. one possible implementation is:
template<bool B, class T = void> struct enable_if {}; template<class T> struct enable_if<true, T> { typedef T type; };
In this way, if we have a template function to judge a certain type, we can easily implement the function we want.
C++11 introduces a large number of judgment types template function:
Using the above type traits, the code is rewritten as follows, which can be easily compiled:
#include <type_traits> #include <iostream> template <typename T> void print(typename std::enable_if<std::is_integral<T>::value, T>::type i) { std::cout << "Integral: " << i << '\n'; } template <typename T> void print(typename std::enable_if<std::is_floating_point<T>::value, T>::type f) { std::cout << "Floating point: " << f << '\n'; } int main() { print<short>(1); print<long>(2); print<double>(3.14); }
std::enable_if and boost::enable_if difference
View boost::enable_if statement:
template <class Cond, class T = void> struct enable_if;
Find that the first parameter is type, and then check boost::enable_if_c declaration and definition of:
template <bool B, class T = void> struct enable_if_c { typedef T type; }; template <class T> struct enable_if_c<false, T> {}; template <class Cond, class T = void> struct enable_if : public enable_if_c<Cond::value, T> {};
boost::enable_if_c and std::enable_if is equivalent
Change the above code to boost version:
#include <boost/utility/enable_if.hpp> #include <type_traits> #include <iostream> template <typename T> void print(typename boost::enable_if<std::is_integral<T>, T>::type i) { std::cout << "Integral: " << i << '\n'; } template <typename T> void print(typename boost::enable_if<std::is_floating_point<T>, T>::type f) { std::cout << "Floating point: " << f << '\n'; } int main() { print<short>(1); print<long>(2); print<double>(3.14); }
Or boost:: Enable_ if_ Version C:
#include <boost/utility/enable_if.hpp> #include <type_traits> #include <iostream> template <typename T> void print(typename boost::enable_if_c<std::is_integral<T>::value, T>::type i) { std::cout << "Integral: " << i << '\n'; } template <typename T> void print(typename boost::enable_if_c<std::is_floating_point<T>::value, T>::type f) { std::cout << "Floating point: " << f << '\n'; } int main() { print<short>(1); print<long>(2); print<double>(3.14); }
So far, std::enable_if and boost::enable_if,boost::enable_ if_ The difference and connection of C is very clear.