基础和派生模板成员之间的重载解析 类
Overload resolution between template members in base and derived classes
Microsoft 编译器 (Visual Studio 2017 15.2) 拒绝以下代码:
#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;
d.f<0>();
d.f<1>();
}
错误是:
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'
Clang 也拒绝了它:
error: no matching member function for call to 'f'
d.f<0>();
~~^~~~
note: candidate template ignored: disabled by 'enable_if' [with n = 0]
using enable_if_t = typename enable_if<_Cond, _Tp>::type;
GCC 完全接受它。哪个编译器是正确的?
加法:
与 SFINAE 的形式
template<int n, typename = std::enable_if_t<n == 0>>
...
template<int n, typename = std::enable_if_t<n == 1>>
GCC 也产生错误:
error: no matching function for call to ‘D::f<0>()’
d.f<0>();
^
note: candidate: template<int n, class> void D::f()
void f()
^
note: template argument deduction/substitution failed:
将 cppleaner 的评论转化为答案:
来自 namespace.udecl#15.sentence-1:
When a using-declarator brings declarations from a base class into a derived class, member functions and member function templates in the derived class override and/or hide member functions and member function templates with the same name, parameter-type-list, cv-qualification, and ref-qualifier (if any) in a base class (rather than conflicting)
不幸的是,模板参数不算在内,并且 f
的参数类型列表为空,不是 const,也没有引用限定符。
Derived::f
所以隐藏 Base::f
.
gcc 接受该代码是错误的。
所以解决方法是默认参数(返回类型也不算):
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) { }
};
Microsoft 编译器 (Visual Studio 2017 15.2) 拒绝以下代码:
#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;
d.f<0>();
d.f<1>();
}
错误是:
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'
Clang 也拒绝了它:
error: no matching member function for call to 'f'
d.f<0>();
~~^~~~
note: candidate template ignored: disabled by 'enable_if' [with n = 0]
using enable_if_t = typename enable_if<_Cond, _Tp>::type;
GCC 完全接受它。哪个编译器是正确的?
加法:
与 SFINAE 的形式
template<int n, typename = std::enable_if_t<n == 0>>
...
template<int n, typename = std::enable_if_t<n == 1>>
GCC 也产生错误:
error: no matching function for call to ‘D::f<0>()’
d.f<0>();
^
note: candidate: template<int n, class> void D::f()
void f()
^
note: template argument deduction/substitution failed:
将 cppleaner 的评论转化为答案:
来自 namespace.udecl#15.sentence-1:
When a using-declarator brings declarations from a base class into a derived class, member functions and member function templates in the derived class override and/or hide member functions and member function templates with the same name, parameter-type-list, cv-qualification, and ref-qualifier (if any) in a base class (rather than conflicting)
不幸的是,模板参数不算在内,并且 f
的参数类型列表为空,不是 const,也没有引用限定符。
Derived::f
所以隐藏 Base::f
.
gcc 接受该代码是错误的。
所以解决方法是默认参数(返回类型也不算):
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) { }
};