1

I have a problem with the following Minimal Example:

enum class modes_t {m1=0u, m2=1u};

class A {
    public:
    static inline A& get(void) noexcept{
        static A inst;
        return inst;
    }
    template<modes_t mode>
    inline void start(void) noexcept {}
};

template<typename T>
class B {
    public:
    static inline void start(void) noexcept {
        T::get().start<modes_t::m1>();
    }
};

int main() {
    B<A>::start();
}

If I compile it with g++ v.7.3, (with -std=c++17 and also with -std=c++14) I get the following errors:

main.cpp: In static member function ‘static void B<T>::start()’:
main.cpp:17:37: error: expected primary-expression before ‘)’ token
         T::get().start<modes_t::m1>();
                                     ^
main.cpp: In instantiation of ‘static void B<T>::start() [with T = A]’:
main.cpp:22:11:   required from here
main.cpp:17:23: error: no match for ‘operator<’ (operand types are ‘<unresolved overloaded function type>’ and ‘modes_t’)
         T::get().start<modes_t::m1>();

So the compiler thinks, that the line T::get().start<modes_t::m1>(); is a less then comparison of T::get().start and modes_t::m1. What should I do, to tell the compiler, that this expression should call start() in class A?

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
byteunit
  • 991
  • 4
  • 15
  • Remember that [scoped enumerations](http://en.cppreference.com/w/cpp/language/enum#Scoped_enumerations) are strongly typed. They can't be implicitly cast to `int`. – Some programmer dude Mar 26 '18 at 07:59
  • sorry, this was a bug from me, it is clear, that this can't be int. I fixed it already in the original post. – byteunit Mar 26 '18 at 08:01
  • Also remember that enumeratoins can "inherit" base type, for example `unsigned`, which will make all values unsigned (so you don't need the explicit `=0u` for example). – Some programmer dude Mar 26 '18 at 08:01

1 Answers1

3

You need to add template keyword to tell the compiler that start is a member function template. e.g.

T::get().template start<modes_t::m1>();
//       ~~~~~~~~

BTW: You can't specify modes_t::m1 as the template argument; start expects an int as its template parameter and there are no implicit conversions from the values of a scoped enumerator to integral types.

songyuanyao
  • 169,198
  • 16
  • 310
  • 405