Search code examples
c++templatesnamespacesoperator-overloadingargument-dependent-lookup

SFINAE-based Operator Overloading across Namespaces


I'm attempting to use an approach which allows for automatic enabling of bitmask operators for strongly typed enum classes. See below header and cpp of an example.

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

The approach in testbitmask.cpp works when everything is in the same namespace, however I would like to separate the SFINAE code in a different namespace from the usage by other classes (see below or 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;
}

This has the effect of not being able to find the overloaded operator in main. Explicitly calling the function works (TWO::A a1 = ONE::operator|(TWO::A::x , TWO::A::y);), but of course is not the desired functionality.

If we move the specialization into namespace ONE, the compiler throws an error: declaration of 'struct ONE::enable_bitmask_operators<TWO::A>' in namespace 'TWO' which does not enclose 'ONE'. I'm wondering if the desired approach is possible in C++?


Solution

  • Your function cannot be found by ADL, you might add some using to allow to use it:

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

    Demo

    using namespace ONE; might be an alternative too.