Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
template_metaprogramming_ru.docx
Скачиваний:
12
Добавлен:
01.07.2025
Размер:
774 Кб
Скачать
☆

Заполнители

(Placeholders)

Заполнители – это класс метафункции mpl::Arg<X>.

Реализация:

Удобные имена «_1», «_2»,...,«_5» являются синонимами для специализаций mpl::Arg<X>, которые определяются по N-му аргументу.

(См. раздел Макроопределения для описания того, как изменить количество поддерживаемых заполнителей.)

namespace boost{

namespace mpl{

namespace placeholders{

template <int N> struct arg; // forward declarations

struct void_; // Признак отсутствия

template <> struct arg<1>

{

template < class A1, class A2 = void_, ..., class Am = void_>

struct apply

{

typedef A1 type; // return the first argument

};

};

// Создаем синоним:

typedef arg<1> _1;

template <>

struct arg<2>

{

template<class A1, class A2, class A3 = void_, ..., class Am = void_>

struct apply

{

typedef A2 type; // return the second argument

};

};

// Создаем синоним:

typedef arg<2> _2;

//more specializations and typedefs...

}

}

}

Вызов класса метафункции эквивалентно вызову вложенной метафункции класса. Когда заполнитель вычиляется в лямбда выражении, он вызывается с фактическим аргументом, возвращая конкретное значение специализации.

Безымянный заполнитель:

Определение:

namespace boost{

namespace mpl{

namespace placeholders{

typedef arg<-1> _; // the unnamed placeholder

}

}

}

Неодходим для специальных режимов. Когда лямбда выражение преобразовывается в класс метафункции mpl::lambda, то такой заполнитель выступает в качестве счетчика, посредством замены безымянного заполнителя на значение конкретной специализации.

Семантика заполнителей:

mpl::plus<_,_>

mpl::plus<_1,_2>

boost::is_same<

_, boost::add_pointer<_>

>

boost::is_same<

_1,

boost::add_pointer<_1>

>

mpl::multiplies<

mpl::plus<_,_>,

mpl::minus<_,_>

>

mpl::multiplies<

mpl::plus<_1,_2>,

mpl::minus<_1,_2>

>

Определение выражений с заполнителями

Выражение заполнителя – это заполнитель или специализация шаблона по крайней мере с одним аргументом, который является выражением заполнителя, т.е. выражение заполнения всегда использует заполнители.

// find the position of a type x in some_sequence such that:

// x is convertible to 'int'

// && x is not 'char'

// && x is not a floating type

typedef mpl::find_if

<

some_sequence,

mpl::and_

<

boost::is_convertible<_1, int>,

mpl::not_<boost::is_same<_1, char>>,

mpl::not_<boost::is_float<_1>>

>

>::type iter;

Реализуем вложенные вызовы для выражений с заполнителями, в идеале, это должно работать аналогично mpl::transform позволяя передавать любые формы:

template <class X>

struct two_pointers : twice<boost::add_pointer<_1>, X>{};

Но, текущая реализация add_poiner не позволит выполнить это.

template <class T>

struct add_pointer

{

typedef T* type;

};

Чтобы быть вызванным дважды add_pointer <_1> должен быть классом метафункции вроде add_pointer_f. Вместо этого нульарная метафункция будет возвращать безсмысленное «_1*». Любая попытка использовать two_pointers потерпит неудачу, когда apply_helper достигнет вложенного «::apply» в теле add_pointer <_1>» оно не будет обнаружено, т.к. в нем содержится лишь «::type». Проблема в том, что необходим универсальный посредник, который будет классом для метафункции наподобии add_pointer <Т>.

Решение: лямбда метафункции

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]