在派生类中重载模板运算符

Cyb*_*ran 5 c++ templates operator-overloading sfinae c++17

给定一个基类和一个派生类,它们都使用SFINAE为特定参数类型提供了有条件启用的运算符:

#include <type_traits>

class Base
{
public:
    template<class T, std::enable_if_t<std::is_scalar_v<T>>* = nullptr>
    void operator>>(T& value) {
    }
};

class Derived: public Base
{
public:
    using Base::operator>>;

    template<class T, std::enable_if_t<!std::is_scalar_v<T>>* = nullptr>
    void operator>>(T& value) {
    }
};


int main(int argc, char *argv[])
{
    int foo;

    Base base;
    base >> foo; // this works

    Derived derived;
    derived >> foo; // this doesn't work, the operator from the base class is not considered
}
Run Code Online (Sandbox Code Playgroud)

然后,即使在适当的using Base::operator>>;声明中已经使可见的调用派生类的实例在基类中定义的运算符,也将无法工作。为什么?如何在不冗长地重复声明/定义的情况下使基类中的运算符可用?

如果所讨论的运算符不是基类中的模板,则不会发生此问题。

编辑:测试与msvc 15.9.7以及clang。

Mic*_*zel 2

我认为这里的问题是 using 声明仅将函数和函数模板的声明带入派生类中,该派生类的签名不会被派生类 [ namespace.udecl]/15的成员覆盖。所以这段代码确实不应该编译。

使用自由函数而不是类成员来解决问题:

#include <type_traits>

class Base
{
public:
    template<class T, std::enable_if_t<std::is_scalar_v<T>>* = nullptr>
    friend void operator>>(Base&, T& value) {
    }
};

class Derived: public Base
{
public:
    template<class T, std::enable_if_t<!std::is_scalar_v<T>>* = nullptr>
    friend void operator>>(Derived&, T& value) {
    }
};

int main()
{
    int foo;

    Base base;
    base >> foo;

    Derived derived;
    derived >> foo;
}
Run Code Online (Sandbox Code Playgroud)

活生生的例子在这里