将指向成员函数的指针作为模板参数传递。为什么这样做?

时间:2009-12-10 17:47:00

标签: c++ templates boost standards

我有一些代码,100%适用于我的用例。我只是想知道是否有人可以解释它是如何以及为什么有效。

我有一个模板类,它位于处理线程和网络通信的一些代码和库用户之间,用于将从服务器接收的数据传递给用户。

template <class Bar,
          class Baz,
          class BazReturnType,
          void (Bar::*BarSetterFunction)(const BazReturnType &),
          BazReturnType (Baz::*BazGetterFunction)(void) const>
class Foo
{
    Foo( Bar *bar )
        : m_bar(bar)
    {
    }

    void FooMemberFunction( const Baz *baz )
    {
        boost::bind( BarSetterFunction, m_bar,
                     boost::bind( BazGetterFunction, baz )() ) ();
    }

    Bar *m_bar;
};

此模板在库中实例化并在库中使用,具体取决于Bar和Baz的类型,如下所示:

typedef Foo<MyBar,
            MyBaz,
            ReturnTypeFromBazGetterFunction,
            &MyBar::ActualSetterFunction,
            &MyBaz::ActualGetterFunction >
    MyFoo;

MyBar *bar = new MyBar;
MyBaz *baz = new MyBaz;
MyFoo *f = new MyFoo( bar );
f->FooMemberFunction( baz );

这一切都有效,boost :: bind调用getter / setter函数来传递数据需要去的地方。 如何以及为什么将指向成员函数的指针作为模板参数传递,就像在这种情况下工作一样?


在回应评论时,我没有意识到指向成员函数的指针是有效的模板参数。这不是我之前在“野外”看过的东西。我尝试了它并且它有效,但我没想到它。

2 个答案:

答案 0 :(得分:34)

我认为有更好的解释为什么可以这样做而不是“因为标准这样说”:

它起作用的原因是因为指向成员的指针是在编译时已知的常量值(指向成员的指针实际上是成员从类的开头的偏移量)。因此,它们可以用作模板的参数,就像任何其他整数常量一样。

另一方面,普通指针不是编译时常量,因为它们依赖于仅在运行时存在的内存布局。它们不能是模板参数。

答案 1 :(得分:2)

当你提出一个类似“为什么某事有效?”的问题时,这意味着它的工作原理在某种程度上令你感到惊讶。除非你解释为什么你发现它令人惊讶,否则不可能回答这个问题。

为什么会这样?因为语言规范明确地说它应该工作。除非您更详细地解释您的疑虑,否则没有其他答案。