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
上面的类是否无效?
[注意:更换fun
用void (*)()
精品工程.但这不是想要的东西.
如上所述将函数传递给类模板是否无效?
完全可以,你正在混合类型和非类型参数.
fun
是一个非类型参数,它是一个函数的地址,就像一个任意数字0x12345678
.
typename T
是一个类型参数.你只能通过它的类型,如int
,MyClass
,double (*)(std::string)
,void (MyClass::*)()
.
你只需要了解事实,你需要编译器支持那些东西或一些非常丑陋的技巧来推断出类型.
如果你正在寻找诡计,那Boost.Typeof
就像你一样有非C++ 0x编码器.它还提供了一个替身auto
与BOOST_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)
使用模板,您可以再次了解该函数类型.
如上所述将函数传递到类模板中是否无效?
是的。换句话说,因为您希望编译器推断出类模板的类型参数,这在 C++ 中根本不可能。回想一下,fun
它本身不是一个类型,它是一个类型的值void (*)()
。但是您的类模板需要类型,而不是值。这就是为什么它行不通。
类型推导仅适用于函数,这意味着即使使用类的构造函数也是如此。因此,如果你编写一个模板化构造函数,那么你可以这样写:
Declare obj(&fun);
Run Code Online (Sandbox Code Playgroud)
这里,只要您在构造函数中,函数的类型就已知,一旦您从构造函数中存在,您就会丢失该信息。所以你可能需要的是:定义一个类AbstractFunctor
(可能是类模板)并从它派生定义另一个类(比如)template<Fun fun> struct Functor
。然后您可以创建一个Functor
可以永远记住函数类型的实例,并将该实例AbstractFunctor*
作为 的成员数据存储在Declare
.
但我认为,即使这样,类型也不能用作Declare::Type
or 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)