基于SFINAE的命名空间中的运算符重载

时间:2019-01-24 16:34:55

标签: c++ templates namespaces operator-overloading argument-dependent-lookup

我正在尝试使用一种允许为强类型枚举类自动启用位掩码运算符的方法。参见下面的示例标题和cpp。

https://www.justsoftwaresolutions.co.uk/files/bitmask_operators.hpp https://www.justsoftwaresolutions.co.uk/files/testbitmask.cpp

当所有东西都在同一个命名空间中时,testbitmask.cpp中的方法可以工作,但是我想将不同命名空间中的SFINAE代码与其他类的使用分开(请参见下文或https://wandbox.org/permlink/05xXaViZT3MVyiBl)。

#include <type_traits>

namespace ONE {
    template<typename E>
    struct enable_bitmask_operators{
        static const bool enable=false;
    };

    template<typename E>
    inline typename std::enable_if<enable_bitmask_operators<E>::enable,E>::type
    operator|(E lhs,E rhs){
        typedef typename std::underlying_type<E>::type underlying;
        return static_cast<E>(
            static_cast<underlying>(lhs) | static_cast<underlying>(rhs));
    }
}

namespace TWO {
    enum class A{ x=1, y=2};
}

namespace ONE {
    template<>
    struct enable_bitmask_operators<TWO::A>{
        static const bool enable=true;
    };
}

int main(){
    TWO::A a1 = TWO::A::x | TWO::A::y;
}

这样的结果是无法在main中找到重载的运算符。显式调用该函数有效(TWO::A a1 = ONE::operator|(TWO::A::x , TWO::A::y);),但当然不是所需的功能。

如果将专业化转移到namespace ONE,则编译器将抛出error: declaration of 'struct ONE::enable_bitmask_operators<TWO::A>' in namespace 'TWO' which does not enclose 'ONE'。我想知道是否可以在C ++中实现所需的方法?

1 个答案:

答案 0 :(得分:2)

ADL无法找到您的函数,您可以添加一些using以允许使用它:

using ONE::operator|;
TWO::A a1 = TWO::A::x | TWO::A::y;

Demo

using namespace ONE;也可能是另一种选择。