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

发布于 2024-11-01 16:48:31 字数 467 浏览 1 评论 0原文

在不知道函数类型的情况下,我使用以下技术声明其指针并初始化函数指针。

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'
}

但是,它会给出编译错误,错误:需要一个类型,得到'fun'。尽管任何方法的类型在编译时都是已知的。 如上所述将函数传递到类 template 中是否无效?

[注意:将 fun 替换为 void (*)()工作正常。但这不是我们想要的。]

Without knowing a function's type, I am declaring its pointer with below technique and initializing a function pointer.

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'
}

However, it gives compile error as, error: expected a type, got ‘fun’. Though the type of any method is known at compile time. Is it invalid to pass a function into a class template as above ?

[Note: replacing fun with void (*)() works fine. But that's not what want.]

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

汹涌人海 2024-11-08 16:48:31

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

完全是的,您混淆了类型参数和非类型参数。
fun 是一个非类型参数,它是一个函数的地址,就像一个任意数0x12345678
typename T 是一个type 参数。您只能传递类型,例如 intMyClassdouble (*)(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

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


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

template<class FPtr>
void myfunc(FPtr otherfunc){
  // use otherfunc
}

并且通过模板,您可以再次了解该函数类型。

Is it invalid to pass a function into a class template as above ?

Totally yes, you're mixing up type and non-type parameters.
fun is a non-type argument, it's an address of a function, like an arbitary number 0x12345678.
typename T is a type parameter. You can only pass it types, like int,MyClass, double (*)(std::string), void (MyClass::*)().
You'll just have to life with the fact, that you need compiler support for that stuff or some really ugly trickery to deduce the type.
If you're in for the trickery, there's Boost.Typeof for non-C++0x coder like you. It also provides a stand-in for auto with BOOST_AUTO, but that is only a short way for writing BOOST_TYPEOF:

int hello(){ return 42; }
BOOST_AUTO(var1,hello()); // type of var1 == int
BOOST_TYPEOF(hello()) var2 = hello(); // same

The problem? You need to help it for every user-defined type you have. See this Ideone example.


Now, most of the time I don't think you need Boost.Typeof. Why? Because if you use a function, you of course need to know the signature, how would you pass the correct arguments otherwise? Or use the return type in a correct way?
The other times are the usage in templates anyways. If you declare a function pointer like auto fptr = &func, then you have the knowledge, that func exists, aka you know its signature and type. For when you don't know that func exists, you need it passed to you anyways, preferably in a template:

template<class FPtr>
void myfunc(FPtr otherfunc){
  // use otherfunc
}

And with a template you have the knowledge of that functions type again.

寄风 2024-11-08 16:48:31

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

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

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

Declare obj(&fun); 

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

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


编辑:

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

Declare<decltype(&fun)>::Type pf = &fun;  
pf(); //call the function

演示: http://ideone.com/

但是,您甚至不需要 Declare,因为您可以这样做:

decltype(&fun) pf = &fun; 
pf(); //call the function   

Is it invalid to pass a function into a class template as above?

Yes. Because what you, in other words, want the compiler to deduce the type parameter for the class template, which simply not possible in C++. Recall that fun itself isn't a type, its a value of type void (*)(). But your class template expects type, not value. That's why it wouldn't work.

Type deduction is possible with functions only, that means even with the constructor of class. So if you write a templated constructor, and then you can write this:

Declare obj(&fun); 

Here the type of the function is known as long as you're in constructor, once you exist from it, you lost the information. So what you probably need is : define a class, say, AbstractFunctor (possibly class template) and derived from it defining an another class say template<Fun fun> struct Functor. Then you can create an instance of Functor which can remember the function type forever, and store the instance in AbstractFunctor* as a member data of Declare.

But I think, even in this way, the type cannot be used as Declare::Type or Declare::AbstractFunctor::Type, simply because the type is stored in an instance of the class; only the instance knows the type. So the getting type using syntax like A::Type is out of the question. And you cannot get type using syntax instance.Type either. All you can do is : call the function, using the instance, like a functor.


EDIT:

If you're allowed to use C++0x's other features (excluding auto), then the problem has a trivial solution:

Declare<decltype(&fun)>::Type pf = &fun;  
pf(); //call the function

Demo : http://ideone.com/

But then, you don't need even Declare, as you can do this instead:

decltype(&fun) pf = &fun; 
pf(); //call the function   
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文