将函数作为类模板参数传递

iam*_*ind 5 c++ templates function-pointers

在不知道函数类型的情况下,我用下面的技术声明它的指针并初始化一个函数指针.

template<typename T>
struct Declare { typedef T Type; }; // for declaring any func ptr

void fun () {}

int main ()
{
  Declare<fun>::Type pf = &fun;  // can't use C++0x 'auto'
}
Run Code Online (Sandbox Code Playgroud)

但是,它给出了编译错误,error: expected a type, got ‘fun’.虽然任何方法的类型在编译时都是已知的.将函数传递给template上面的类是否无效?

[注意:更换funvoid (*)()精品工程.但这不是想要的东西.

Xeo*_*Xeo 5

如上所述将函数传递给类模板是否无效?

完全可以,你正在混合类型和非类型参数.
fun是一个非类型参数,它是一个函数的地址,就像一个任意数字0x12345678.
typename T是一个类型参数.你只能通过它的类型,如int,MyClass,double (*)(std::string),void (MyClass::*)().
你只需要了解事实,你需要编译器支持那些东西或一些非常丑陋的技巧来推断出类型.
如果你正在寻找诡计,那Boost.Typeof就像你一样有非C++ 0x编码器.它还提供了一个替身autoBOOST_AUTO,但这只是写一个短的路BOOST_TYPEOF:

int hello(){ return 42; }
BOOST_AUTO(var1,hello()); // type of var1 == int
BOOST_TYPEOF(hello()) var2 = hello(); // same
Run Code Online (Sandbox Code Playgroud)

问题?您需要为每个用户定义的类型提供帮助.请参阅此Ideone示例.


现在,大多数时候我认为你不需要Boost.Typeof.为什么?因为如果你使用一个函数,你当然需要知道签名,否则你将如何传递正确的参数?或者以正确的方式使用返回类型?
其他时候是模板中的用法.如果你声明一个类似的函数指针auto fptr = &func,那么你就拥有知识,即func知道它的签名和类型.因为当您不知道func存在时,无论如何都需要将它传递给您,最好是在模板中:

template<class FPtr>
void myfunc(FPtr otherfunc){
  // use otherfunc
}
Run Code Online (Sandbox Code Playgroud)

使用模板,您可以再次了解该函数类型.


Naw*_*waz 3

如上所述将函数传递到类模板中是否无效?

是的。换句话说,因为您希望编译器推断出类模板的类型参数,这在 C++ 中根本不可能。回想一下,fun它本身不是一个类型,它是一个类型的void (*)()。但是您的类模板需要类型,而不是值。这就是为什么它行不通。

类型推导仅适用于函数,这意味着即使使用类的构造函数也是如此。因此,如果你编写一个模板化构造函数,那么你可以这样写:

Declare obj(&fun); 
Run Code Online (Sandbox Code Playgroud)

这里,只要您在构造函数中,函数的类型就已知,一旦您从构造函数中存在,您就会丢失该信息。所以你可能需要的是:定义一个类AbstractFunctor(可能是类模板)并从它派生定义另一个类(比如)template<Fun fun> struct Functor。然后您可以创建一个Functor可以永远记住函数类型的实例,并将该实例AbstractFunctor*作为 的成员数据存储在Declare.

但我认为,即使这样,类型也不能用作Declare::Typeor Declare::AbstractFunctor::Type,仅仅因为类型存储在类的实例中;只有实例知道类型。所以使用像这样的语法获取类型A::Type是不可能的。而且您也无法使用语法获取类型instance.Type您所能做的就是:使用实例调用函数,就像函子一样。


编辑:

如果允许您使用 C++0x 的其他功能(不包括 auto),那么问题就有一个简单的解决方案:

Declare<decltype(&fun)>::Type pf = &fun;  
pf(); //call the function
Run Code Online (Sandbox Code Playgroud)

演示: http: //ideone.com/

但是,你不需要 Even Declare,因为你可以这样做:

decltype(&fun) pf = &fun; 
pf(); //call the function   
Run Code Online (Sandbox Code Playgroud)