Selecting a Member Function Using Enable_If Conditions
The task is to determine the invocation of a member function based on a class template parameter. The following code snippet attempts to achieve this:
<code class="cpp">#include <iostream> #include <type_traits> template<typename T> struct Point { void MyFunction(typename std::enable_if<std::is_same<T, int>::value, T &>::type* = 0) { std::cout << "T is int." << std::endl; } void MyFunction(typename std::enable_if<!std::is_same<T, int>::value, float &>::type* = 0) { std::cout << "T is not int." << std::endl; } };</code>
However, this code fails to compile with the error "no type named ‘type’ in ‘struct std::enable_if’".
SFINAE in Action
The key to understanding this issue lies in the concept of Substitution Failure Is Not An Error (SFINAE). Enable_if allows conditional compilation based on template arguments. In this case, the template argument T is already known when the member functions are instantiated. Therefore, the condition is evaluated at instantiation time and the corresponding function is selected.
Fixing the Code
To rectify this, we need to introduce a dummy template argument that is defaulted to T. This allows the SFINAE mechanism to work as intended. The modified code would look like this:
<code class="cpp">template<typename T> struct Point { template<typename U = T> typename std::enable_if<std::is_same<U, int>::value>::type MyFunction() { std::cout << "T is int." << std::endl; } template<typename U = T> typename std::enable_if<std::is_same<U, float>::value>::type MyFunction() { std::cout << "T is not int." << std::endl; } };</code>
Preventing Explicit Member Function Specialization
As pointed out by HostileFork, the original code allows the explicit specification of template arguments for the member functions, which could lead to incorrect results. To prevent this, we can add a static_assert that checks if any template arguments are provided. This ensures that the correct member function is always invoked based on the template argument T. The modified code would be:
<code class="cpp">template<typename T> struct Point { template<typename... Dummy, typename U = T> typename std::enable_if<std::is_same<U, int>::value>::type MyFunction() { static_assert(sizeof...(Dummy)==0, "Do not specify template arguments!"); std::cout << "T is int." << std::endl; } template<typename... Dummy, typename U = T> typename std::enable_if<std::is_same<U, float>::value>::type MyFunction() { static_assert(sizeof...(Dummy)==0, "Do not specify template arguments!"); std::cout << "T is not int." << std::endl; } };</code>
The above is the detailed content of How to Select a Member Function Based on a Template Parameter Using `enable_if`?. For more information, please follow other related articles on the PHP Chinese website!