在不知道函数类型的情况下,我用下面的技术声明它的指针并初始化一个函数指针。
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'
}
但是,它会将编译错误称为error: expected a type, got ‘fun’
。虽然任何方法的类型在编译时都是已知的。 将函数传递给上述类template
是否无效?
[注意:将fun
替换为void (*)()
可以正常工作。但那不是想要的。]
答案 0 :(得分:5)
如上所述将函数传递给类模板是否无效?
完全可以,你正在混合类型和非类型参数
fun
是非类型参数,它是函数的地址,如仲裁号0x12345678
。
typename T
是类型参数。您只能传递类型,例如int
,MyClass
,double (*)(std::string)
,void (MyClass::*)()
。
你只需要了解事实,你需要编译器支持那些东西或一些非常丑陋的技巧来推断出类型。
如果你正在寻找诡计,那么像你这样的非C ++ 0x编码器有Boost.Typeof
。它还为auto
BOOST_AUTO
提供了一个替代,但这只是撰写BOOST_TYPEOF
的简短方法:
int hello(){ return 42; }
BOOST_AUTO(var1,hello()); // type of var1 == int
BOOST_TYPEOF(hello()) var2 = hello(); // same
问题?您需要为每个用户定义的类型提供帮助。请参阅this Ideone example。
现在,大多数时候我认为你不需要Boost.Typeof。为什么?因为如果你使用一个函数,你当然需要知道签名,否则你将如何传递正确的参数?或者以正确的方式使用返回类型?
其他时候是模板中的用法。如果你声明一个像auto fptr = &func
这样的函数指针,那么你就知道func
存在,你知道它的签名和类型。因为当您不知道func
存在时,无论如何都需要将它传递给您,最好是在模板中:
template<class FPtr>
void myfunc(FPtr otherfunc){
// use otherfunc
}
使用模板,您可以再次了解该功能类型。
答案 1 :(得分:3)
如上所述将函数传递给类模板是否无效?
是。因为,换句话说,你希望编译器推导出类模板的 type 参数,这在C ++中是不可能的。回想一下fun
本身不是类型,它是类型为void (*)()
的值。但是你的类模板需要类型而不是值。这就是为什么它不起作用。
类型推导只能使用函数,即使使用类的构造函数也是如此。因此,如果你编写一个模板化的构造函数,那么你可以这样写:
Declare obj(&fun);
这里的函数类型是已知的,只要你在构造函数中,一旦你存在它,你就丢失了信息。所以你可能需要的是:定义一个类,比如说,AbstractFunctor
(可能是类模板),并从中派生出来定义另一个类template<Fun fun> struct Functor
。然后,您可以创建Functor
的实例,该实例可以永远记住函数类型,并将实例存储在AbstractFunctor*
中作为Declare
的成员数据。
但我认为,即使这样,该类型也不能用作Declare::Type
或Declare::AbstractFunctor::Type
,因为类型存储在实例中< / em>班级;只有实例知道类型。因此,使用A::Type
之类的语法获取类型是不可能的。并且您无法使用语法instance.Type
获取类型。您所能做的就是:使用实例调用函数,就像函子一样。
编辑:
如果你被允许使用C ++ 0x的其他功能(不包括auto),那么这个问题有一个简单的解决方案:
Declare<decltype(&fun)>::Type pf = &fun;
pf(); //call the function
但是,你甚至不需要Declare
,因为你可以这样做:
decltype(&fun) pf = &fun;
pf(); //call the function