Странный синтаксис шаблона в & lt; функциональном & gt;

Я искал исходный код для std::function а также std::bind в gcc-4.7.2, и натолкнулся на некоторый синтаксис, используемый для указателей на функции-члены, которые я не понимаю.

Что я не понимаю, так это специализация _Maybe_wrap_member_pointer:

template<typename _Tp, typename _Class>
struct _Maybe_wrap_member_pointer<_Tp _Class::*> // note no comma here
  • Почему нет запятой между _Tp а также _Class::*?

  • Данная функция-член void foo::bar() (в моем примере приложения ниже), что будет _Tp а также _Class::* разрешить здесь?

Ниже приведен пример моего приложения, которое связывает указатель на функцию-член и объект. (Я вытащил исходный код, относящийся к std::bind специализации / внутренние функции члена)

#include <iostream>
#include <functional>

template<typename T>
struct _Maybe_wrap_member_pointer;

template<typename _Tp, typename _Class>
struct _Maybe_wrap_member_pointer<_Tp _Class::*> // <-- I don't understand this
{                                                // why not <_Tp, _Class::*>
typedef std::_Mem_fn<_Tp _Class::*> type;

static type __do_wrap(_Tp _Class::* __pm)
{
return type(__pm);
}
};

template<typename _Func, typename... _BoundArgs>
struct _Bind_helper
{
typedef _Maybe_wrap_member_pointer<typename std::decay<_Func>::type> __maybe_type;

typedef typename __maybe_type::type __func_type;
typedef std::_Bind<__func_type(typename std::decay<_BoundArgs>::type...)> type;
};

template<typename _Func, typename... _BoundArgs>
inline
typename _Bind_helper<_Func, _BoundArgs...>::type
bind(_Func&& __f, _BoundArgs&&... __args)
{
typedef _Bind_helper<_Func, _BoundArgs...>   __helper_type;
typedef typename __helper_type::__maybe_type __maybe_type;
typedef typename __helper_type::type         __result_type;

return __result_type(__maybe_type::__do_wrap(std::forward<_Func>(__f)),
std::forward<_BoundArgs>(__args)...);
}

struct foo
{
void bar()
{
std::cout << __func__ << std::endl;
}
};

int main()
{
foo f;

std::function<void()> fun = bind(&foo::bar, f);
fun();

exit(0);
}

2

Решение

Это действительно синтаксис, используемый для указания типов указателей на элементы в качестве параметров шаблона.

Предположим, у вас есть класс

struct Bar
{
int n;
};

затем указатель на член Bar::n должен был бы иметь свой тип, объявленный как int Bar::*:

int Bar::* p = &Bar::n;

Обратите внимание, что int относится к типу, на который указывает указатель, и Bar::* означает «указатель на член Bar».

Теперь функция вашего примера,

template<typename _Tp, typename _Class>
struct _Maybe_wrap_member_pointer<_Tp _Class::*> // note no comma here

принимает аргумент шаблона (только один!), который представляет тип указателя на член класса _Class, указывая на нестатический член данных типа _Tp,

Это специализация шаблона шаблона класса, который имеет только один параметр шаблона:

template <typename T>
struct _Maybe_wrap_member_pointer
{ };

Мы можем создать экземпляр специализации, используя простой класс, описанный выше:

_Maybe_wrap_member_pointer<int Bar::*>

или используя decltype:

_Maybe_wrap_member_pointer<decltype(&Bar::n)>

В обоих случаях, _Tp выводится int, а также _Class выводится Bar,

7

Другие решения

  • Почему между _Tp и _Class :: * нет запятой?

jogojapan ответил на эту часть

  • Учитывая функцию-член void foo :: bar () (в моем примере приложения ниже), что решат _Tp и _Class :: * здесь?

Тип, такой как Tp Class::* может представлять указатель на данные члена или же указатель на функцию-член, в последнем случае Tp будет тип функции.

В вашем примере _Tp будет тип функции void () а также _Class будет foo

1

По вопросам рекламы [email protected]