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

StackOverflow https://stackoverflow.com/questions/1882740

Вопрос

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


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

Это было полезно?

Решение

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

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

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

Другие советы

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top