3

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++?

Jarod42
  • 203,559
  • 14
  • 181
  • 302
singhh23
  • 97
  • 7

1 Answers1

3

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.

Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • I suppose this is acceptable - would prefer not to have `using` required in every cpp that uses the enum, and ideally would prefer not to have `using ONE::operator|` in the header as it is pretty generic. I can live with wrapping the enum class in another namespace and using it inside that instead. Will wait another day in case there are any other approaches, though I believe there is not. – singhh23 Jan 24 '19 at 16:47
  • 1
    It is similar to [`operator ""s`](https://en.cppreference.com/w/cpp/string/basic_string/operator%22%22s)' usage for `std`. – Jarod42 Jan 24 '19 at 16:54