4

Consider the code:

#include <type_traits>
#include <iostream>

struct test1 {
    void Invoke() {};
};

struct test2 {
    template<typename> void Invoke() {};
};


enum class InvokableKind {
    NOT_INVOKABLE,
    INVOKABLE_FUNCTION,
    INVOKABLE_FUNCTION_TEMPLATE
};

template<typename Functor, class Enable = void>
struct get_invokable_kind {
    const static InvokableKind value = InvokableKind::NOT_INVOKABLE;
};

template<typename Functor>
struct get_invokable_kind<
  Functor,
  decltype(Functor().Invoke())
  >
{
    const static InvokableKind value = InvokableKind::INVOKABLE_FUNCTION;
};

template<typename Functor>
struct get_invokable_kind<
  Functor,
  decltype(Functor().Invoke<void>())
  >
{
    const static InvokableKind value = InvokableKind::INVOKABLE_FUNCTION_TEMPLATE;
};


int main() {
    using namespace std;

    cout << (get_invokable_kind<test1>::value == InvokableKind::INVOKABLE_FUNCTION) << endl;
    cout << (get_invokable_kind<test2>::value == InvokableKind::INVOKABLE_FUNCTION_TEMPLATE) << endl;

}

What I'm trying to do is to create a metafunction for testing a specific definition of "invokability". And now I'm stuck on this compilation error on GCC 4.5.3:

prog.cpp:37:3: error: template argument 2 is invalid

What does it mean? Why can I specialize on decltype(Functor().Invoke()), but can not on decltype(Functor().Invoke<void>())?

ulidtko
  • 14,740
  • 10
  • 56
  • 88

1 Answers1

6

You need to qualify it with template because of parsing ambiguities:

 decltype(Functor().template Invoke<void>())
                    ^^^^^^^^

Related: Where and why do I have to put the "template" and "typename" keywords?

Also, consider using std::declval rather than Functor() constructor.

Community
  • 1
  • 1
Pubby
  • 51,882
  • 13
  • 139
  • 180