简体   繁体   English

将函数作为参数传递给模板类的模板方法

[英]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. 这告诉编译器显式call是一个模板,因此它应该将<视为模板参数的开头而不是常规的小于运算符。

This should use template as well: 这也应该使用template

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). 但是,如果没有template关键字,一旦call_f实际被实例化,你最终会得到一个错误(可能 - 它有奇怪的方式可以工作)。

The first two examples are okay without using the template keyword. 前两个示例没有使用template关键字是可以的。 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. 由于类型不依赖于模板参数,因此可以在解析call_f确定call是模板。

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 . 即使在定义了call_f之后,这种特殊化也可能发生,因此编译器在解析call_f时不能依赖call_any的主要模板。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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