简体   繁体   English

模板参数推导指向成员函数的指针?

[英]template argument deduction for pointer to member function?

I am trying to build a statically bound delegate class, where the member function is bound at compile time, thereby aiding optimisation. 我正在尝试构建一个静态绑定的委托类,其中成员函数在编译时绑定,从而帮助优化。

I have the following code which works exactly how I want it to: 我有以下代码,它完全符合我的要求:

#include <iostream>

namespace thr {

template<typename T, T func>
struct delegate;

template<typename R,
         typename C,
         typename... A,
         R  (C::* mem_fun)(A...)>
struct delegate<R(C::*)(A...), mem_fun>
{ 
  delegate(C* obj_)
    : _obj(obj_)
  {}

  R operator()(A... a)
  {
    return (_obj->*mem_fun)(a...);
  }
 private:
  C* _obj;
};

} // namespace thr

struct foo
{
  double bar(int i, int j)
  { 
    return (double)i / (double)j;
  } 
};

int main()
{
  foo f;

  typedef thr::delegate<decltype(&foo::bar), &foo::bar> cb;      
  cb c(&f);

  std::cout << c(4, 3);
  return 0;
}

However, the usage is not very elegant: 但是,使用不是很优雅:

thr::delegate<decltype(&foo::bar), &foo::bar>

I would like to use a function template which deduces the template parameters and returns a delegate instance; 我想使用一个函数模板,它推导出模板参数并返回一个委托实例; something along the lines of (this code does not compile): 一些事情(这段代码不能编译):

template<typename C, typename T, T func>
thr::delegate<T, func> bind(T func, C* obj)
{
  return thr::delegate<decltype(func), func>(obj);
} 

This would allow for more elegant syntax: 这将允许更优雅的语法:

auto cb = bind(&foo::bar, &f);

Is it possible to deduce a non-type parameter in a function template? 是否可以在函数模板中推导出非类型参数?

Is what I'm trying to achieve even possible? 我正在努力实现的目标是什么?

Would std::function help? std :: function会有帮助吗? http://www2.research.att.com/~bs/C++0xFAQ.html#std-function Your example looks quite close. http://www2.research.att.com/~bs/C++0xFAQ.html#std-function您的示例看起来非常接近。

I think the compiler supplied STL does pretty horrible things to make it work smoothly. 我认为编译器提供的STL做了非常可怕的事情,使它顺利运行。 You may want to have a look at as an example before giving up. 在放弃之前,你可能想看一个例子。

Edit: I went out and tried what you try to accomplish. 编辑:我出去尝试了你想要完成的事情。 My conclusion is a compile error: 我的结论是编译错误:

  • The return type of the bind (delegate) must name the pointer to member because it is your own requirement. bind(委托)的返回类型必须将指针命名为member,因为它是您自己的要求。
  • bind should accept the name of the pointer to member to be elegant (ie your requirement) bind应该接受指向成员的指针的名称(即你的要求)
  • Compiler requires you to not shadow the template parameter with a function parameter or use the name in both parameters and return type. 编译器要求您不要使用函数参数隐藏模板参数,或者在参数和返回类型中使用名称。

Therefore one of your requirements must go. 因此,您的一个要求必须去。

Edit 2: I took the liberty of changing your delegate so bind works as you wish. 编辑2:我冒昧地改变了你的委托,所以bind可以按你的意愿工作。 bind might not be your priority though. 绑定可能不是你的优先事项。

#include <iostream>

namespace thr {


template<typename C,typename R,typename... A>
struct delegate
{ 
 private:
  C* _obj;
  R(C::*_f)(A...);
  public:
  delegate(C* obj_,R(C::*f)(A...))
    : _obj(obj_),_f(f)
  {}

  R operator()(A... a)
  {
    return (_obj->*_f)(a...);
  }

};

} // namespace thr

template<class C,typename R,typename... A> thr::delegate<C,R,A...> bind(R(C::*f)(A...),C* obj){
    return thr::delegate<C,R,A...>(obj,f);
}

struct foo
{
  double bar(int i, int j)
  { 
    return (double)i / (double)j;
  }
};

int main()
{
  foo f;
  auto c = bind(&foo::bar, &f);
  std::cout << c(4, 6);
  return 0;
}

It is possible to deduce other entities than types in a function signature, but function parameters themselves cannot then be used as template parameters. 可以推导出除函数签名中的类型之外的其他实体,但是函数参数本身不能用作模板参数。

Given: 鉴于:

template <size_t I> struct Integral { static size_t const value = I; };

You can have: 你可以有:

template <size_t N>
Integral<N> foo(char const (&)[N]);

But you cannot have: 但你不能拥有:

Integral<N> bar(size_t N);

In the former case, N as the size of the array is part of the type of the argument, in the latter case, N is the argument itself. 在前一种情况下, N作为数组的大小是参数类型的一部分,在后一种情况下, N是参数本身。 It can be noticed that in the former case, N appeared in the template parameters list of the type signature. 可以注意到,在前一种情况下, N出现在类型签名的模板参数列表中。

Therefore, if indeed what you want is possible, the member pointer value would have to appear as part of the template parameter list of the function signature. 因此,如果您确实需要,则成员指针必须显示为函数签名的模板参数列表的一部分。

There may be a saving grace using constexpr , which can turn a regular value into a constant fit for template parameters: 使用constexpr可能会有一个保存优雅,它可以将常规值转换为模板参数的常量值:

constexpr size_t fib(size_t N) { return N <= 1 ? 1 : fib(N-1) + fib(N-2); }

Integral<fib(4)> works;

But I am not savvy enough to go down that road... 但我不够精明,不能走那条路......

I do however have a simple question: why do you think this will speed things up ? 但是我有一个简单的问题:为什么你认为这会加快速度? Compilers are very good at constant propagation and inlining, to the point of being able to inline calls to virtual functions when they can assess the dynamic type of variables at compilation. 编译器非常擅长于常量传播和内联,以便能够在编译时评估变量的动态类型时内联调用虚函数。 Are you sure it's worth sweating over this ? 你确定值得大汗淋漓吗?

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

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