Overload resolution between template members in base and derived classes

The Microsoft compiler (Visual Studio 2017 15.2) rejects the following code:

#include <type_traits> struct B { template<int n, std::enable_if_t<n == 0, int> = 0> void f() { } }; struct D : B { using B::f; template<int n, std::enable_if_t<n == 1, int> = 0> void f() { } }; int main() { D d; df<0>(); df<1>(); } 

Error:

 error C2672: 'D::f': no matching overloaded function found error C2783: 'void D::f(void)': could not deduce template argument for '__formal' note: see declaration of 'D::f' 

Klang also rejects it:

 error: no matching member function for call to 'f' df<0>(); ~~^~~~ note: candidate template ignored: disabled by 'enable_if' [with n = 0] using enable_if_t = typename enable_if<_Cond, _Tp>::type; 

GCC takes it great. Which compiler is right?

Addition:

With SFINAE in shape

 template<int n, typename = std::enable_if_t<n == 0>> ... template<int n, typename = std::enable_if_t<n == 1>> 

GCC also generates an error:

 error: no matching function for call to 'D::f<0>()' df<0>(); ^ note: candidate: template<int n, class> void D::f() void f() ^ note: template argument deduction/substitution failed: 
+5
source share
1 answer

Turning cppleaner comment into response:

From namespace.udecl # 15.sentence-1 :

When the declarator utility brings declarations from the base class to the derived class, the member functions and member function templates in the derived class override and / or hide the member functions and member member templates with the same name, the list of type parameters, cv- qualification and ref-qualifier (if any) in the base class (and not in conflict)

Unfortunately, the template parameter does not count, and both f have an empty list of type parameters, are not constants, and do not contain a ref qualifier.

Derived::f , therefore hides Base::f .

gcc mistakenly accepts this code.

So, the way to fix this is the default argument (the return type is not taken into account either):

 struct B { template <int n> void f(std::enable_if_t<n == 0>* = nullptr) { } }; struct D : B { using B::f; template <int n> void f(std::enable_if_t<n == 1>* = nullptr) { } }; 
+2
source

Source: https://habr.com/ru/post/1270693/


All Articles