Подтвердить что ты не робот

Передача указателя на функцию-член в качестве аргумента шаблона. Почему это работает?

У меня есть код, который 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, чтобы передавать данные туда, где они должны идти. Как и почему работают передающие указатели на функции-члены как аргумент шаблона, как в этом случае?


В ответ на комментарии я не понял, что указатели на функции-члены являются допустимыми аргументами шаблона. Это не то, что я видел "в дикой природе" раньше. Я попробовал, и это сработало, но я этого не ожидал.

4b9b3361

Ответ 1

Я думаю, что есть лучшее объяснение, почему это возможно сделать, чем "потому что стандарт говорит так":

Причина, по которой он работает, заключается в том, что указатели-члены являются постоянными значениями, известными во время компиляции (указатель-член является фактически смещением члена от начала класса). Таким образом, они могут использоваться в качестве параметров шаблонов, как и любая другая целочисленная константа.

С другой стороны, обычные указатели не являются константами времени компиляции, поскольку они зависят от макета памяти, который существует только во время выполнения. Они не могут быть аргументами шаблона.

Ответ 2

Когда вы задаете вопрос по принципу "почему что-то работает?", это подразумевает, что тот факт, что он работает, как-то удивляет вас. Невозможно ответить на вопрос, если вы не объясните, почему вы считаете это неожиданным.

Почему это работает? Потому что спецификация языка явно говорит, что она будет работать. Нет другого ответа, пока вы не объясните свои проблемы более подробно.