c++ - 基类和派生类中的模板成员之间的重载解析

标签 c++ c++14 sfinae overload-resolution using-declaration

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) { }
};

关于c++ - 基类和派生类中的模板成员之间的重载解析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54101105/

相关文章:

c++ - 从 FloatingLiteral/APFloat 获取原始解析数字

c++ - 获取缺陷对象的坐标值

c++ - 需要 API 将日志消息发送到服务器

c++ - 使用 repaint() 刷新停止工作

C++ 初始化列表和默认值

c++ - 模拟虚方法的构造函数行为

c++ - SFINAE 检查继承的成员函数

c++ - 在 `expressions` 类中处理对 `vector_binary_operation` 的引用,而没有不必要的拷贝

c++ - 如何在 C++ 编译时检测结构的成员是否是位域?

c++ - 铿锵错误 : note: candidate constructor (the implicit move constructor) not viable: