简体   繁体   中英

passing function as parameter to template method of template class

The following code looks legitimate but doesn't compile

void f() {}

template<bool>
struct call_any
{
    template<typename F>
    static void call(F f) {}
};

template<bool B>
void call_f()
{
    call_any<true>::call<void (&)()>(f);  // OK
    call_any<false>::call<void (&)()>(f); // OK
    call_any<B>::call<void()>(f);         // OK
    call_any<B>::call<void (&)()>(f); // expected primary-expression before '>'
}

Why there is an error and what does it mean?

When you are dealing with types that are dependent on the template parameters within a template, the compiler doesn't know what kinds of things the members of that type are. Unless you specify otherwise, it assumes that the members are not types and not templates. Because of this, it is trying to treat < as a less-than operator, but it becomes impossible to parse the expression that way by the time it reaches the > .

To get rid of the error you should use this instead:

call_any<B>::template call<void (&)()>(f);

This tells the compiler explicitly that call is a template, so it should treat the < as the beginning of the template parameters and not a regular less-than operator.

This should use template as well:

call_any<B>::call<void()>(f); 

The only reason you don't see the error on this line is that there is a way to parse it as a non-template:

(call_any<B>::call < void() ) > (f);

Although odd, it is syntatically valid, so the compiler gets past that line, and the first error you see is the one you mention. However, without the template keyword, you would eventually get an error once call_f was actually instantiated (probably -- there are weird ways it could work).

The first two examples are okay without using the template keyword. Since the type isn't dependent on the template parameters, it can be determined that call is a template while call_f is being parsed.

You might ask: "Why can't the compiler figure out it is a template? I've defined it as a template in the code right above!". The issue is specialization. You could specialize the template and do something completely different than what the primary template specifies:

template<>
struct call_any<false>
{
    static const int call = 5;
};

This specialization could occur even after call_f is defined, so the compiler can't rely on what the primary template for call_any says when it is parsing call_f .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM