代码之家  ›  专栏  ›  技术社区  ›  Grant Limberg

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

  •  21
  • Grant Limberg  · 技术社区  · 15 年前

    我有一些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 回复  |  直到 13 年前
        1
  •  34
  •   kaalus    13 年前

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

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

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

        2
  •  2
  •   AnT stands with Russia    15 年前

    当你按照“为什么”这句话提问时 某物 工作吗?”它意味着它的工作对你来说是令人惊讶的。除非你解释,否则不可能回答这个问题。 为什么 你觉得很惊讶。

    为什么工作?因为语言规范明确指出它应该起作用。没有其他答案,除非你更详细地解释你的担忧。