the articles https://www.fluentcpp.com/2018/05/15/make-sfinae-pretty-1-what-value-sfinae-brings-to-code/ and https://www.fluentcpp.com/2018/05/18/make-sfinae-pretty-2-hidden-beauty-sfinae/ explain how to use SFINAE for class methods. The first implementation of the class is the following:
template<typename T>
class MyClass
{
public:
void f(T const& x);
void f(T&& x);
};
To prevent the use of the second function f if T is a reference, the article presents the following solution:
template<typename T>
class MyClass
{
public:
void f(T const& x){}
template<typename T_ = T, typename = std::enable_if_t<!std::is_reference_v<T_>>>
void f(T&& x){}
};
Wouldn't it be easier/cleaner to substitute the return type of the method by std::enable_if? So the class would look like the following:
template<typename T>
class MyClass
{
public:
void f(T const& x){}
std::enable_if_t<!std::is_reference_v<T>>> f(T&& x){}
};
First, your technique doesn't work. T is a fixed type within MyClass enable_if_t<false> is ill-formed. No substitution is being performed, so this isn't substitution failure, it is just an ill-formed signature.
You can fix it to some extent with
template<class T_=T>
std::enable_if_t<!std::is_reference_v<T_>>> f(T_&& x){}
Now, this technique (using the return value) doesn't work (A) on constructors, and (B) when you want to deduce the return type.
It also mixes the return type with SFINAE code; the two have nothing to do with each other.
On top of all of this, both this technique and the original one you are copying has some questionable interaction with the "all templates must have a valid instantiation". I am still unclear if this applies to every template method of a fixed template class instantiation or not; if so, then you have to ensure that some T_ would make the body valid.
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