Default template argument when using std::enable_if as templ. param.: why OK with two template functions that differ only in the enable_if parameter?

Notes A common mistake is to declare two function templates that differ only in their default template arguments. This is illegal because default template arguments are not part of function template’s signature, and declaring two different function templates with the same signature is illegal. Your functions don’t differ only in their default template arguments, they … Read more

How Does std::enable_if work?

As is mentioned in comment by 40two, understanding of Substitution Failure Is Not An Error is a prerequisite for understanding std::enable_if. std::enable_if is a specialized template defined as: template<bool Cond, class T = void> struct enable_if {}; template<class T> struct enable_if<true, T> { typedef T type; }; The key here is in the fact that … Read more

Template specialization and enable_if problems [duplicate]

Default template arguments are not part of the signature of a function template. So in your example you have two identical overloads of less, which is illegal. clang complains about the redefinition of the default argument (which is also illegal according to ยง14.1/12 [temp.param]), while gcc produces the following error message: error: redefinition of ‘template<class … Read more

How to write a type trait `is_container` or `is_vector`?

Look, another SFINAE-based solution for detecting STL-like containers: template<typename T, typename _ = void> struct is_container : std::false_type {}; template<typename… Ts> struct is_container_helper {}; template<typename T> struct is_container< T, std::conditional_t< false, is_container_helper< typename T::value_type, typename T::size_type, typename T::allocator_type, typename T::iterator, typename T::const_iterator, decltype(std::declval<T>().size()), decltype(std::declval<T>().begin()), decltype(std::declval<T>().end()), decltype(std::declval<T>().cbegin()), decltype(std::declval<T>().cend()) >, void > > : public std::true_type {}; … Read more

Why should I avoid std::enable_if in function signatures

Put the hack in the template parameters. The enable_if on template parameter approach has at least two advantages over the others: readability: the enable_if use and the return/argument types are not merged together into one messy chunk of typename disambiguators and nested type accesses; even though the clutter of the disambiguator and nested type can … Read more

Disambiguate class-member in multiple inheritance

Here’s a simpler example: template <typename T> class Base2 { public: void foo(T ) { } }; struct Derived: public Base2<int>, public Base2<double> {}; int main() { Derived().foo(0); // error } The reason for that comes from the merge rules [class.member.lookup]: Otherwise (i.e., C does not contain a declaration of f or the resulting declaration … Read more

Why doesn’t SFINAE (enable_if) work for member functions of a class template?

SFINAE only works for deduced template arguments, i.e. for function templates. In your case, both templates are unconditionally instantiated, and the instantiation fails. The following variant works: struct Foo { template <typename T> typename std::enable_if<std::is_same<T, A>::value>::type bar(T) {} // … (further similar overloads) … }; Now Foo()(x) causes at most one of the overloads to … Read more