Here is the MWE, how this could be achieved:
#include <iostream> using namespace std; struct multi; struct single; template<class T, class Q> struct dummy { dummy(T value) : m_value(value) { } // using enable_if_t in template argument template<class _Q = Q, enable_if_t<is_same<_Q, single>::value && is_same<_Q, Q>::value, int> = 1> T increment() { return ++m_value; } // using enable_if_t in method return type template<class _Q = Q> enable_if_t<is_same<_Q, multi>::value && is_same<_Q, Q>::value, T> //enable_if_t<is_same<_Q, multi>::value, T> // (*) increment(T delta) { return (m_value += delta); } T m_value; }; int main() { dummy<double, multi> m(47.10); //cout << m.increment() << endl; // error as expected cout << m.increment(.01) << endl; dummy<int, single> s(41); cout << s.increment() << endl; cout << s.increment<single>() << endl; //cout << s.increment(1) << endl; // error as expected //cout << s.increment<multi>(1) << endl; // not an error when using (*) }
Exit
Using c++ (Debian 6.2.1-5) 6.2.1 20161124 , we get:
47.11 42 43
Development
We need to set up methods to make SFINAE work at all. We cannot use something like
std::enable_if_t<std::is_same<_Q, multiple_increment>::value, T> increment() ...
since this fails when creating the template instance dummy<T, single_increment> instead of failing to replace dummy<T, single_increment> the template parameters .
In addition, we want the user to be able to use methods without actually providing a method template parameter. Therefore, we make the default template parameter of the _Q method equal to Q
Finally, to actually cause a compiler error when using an unwanted method even when providing a method template parameter, only enable_if_t method if the _Q method template parameter is actually the same type as the corresponding Q template template parameter.
schlimmchen
source share