Изменение порядка переменных параметров

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

Вот конкретный пример. Предположим, что базовым типом каждого параметра (без ссылок, ссылок на rvalue, указателей или квалификаторов )является либо char, int, либо float. Как сделать так, чтобы сначала отображались все параметры базового типа char, а затем все параметры базового типаint(что оставляет параметры базового типа floatпоследними ). Относительный порядок, в котором задаются параметры, не должен нарушаться в подсписках однородного базового типа.

Пример:foo::foo()вызывается с аргументами float a, char&& b, const float& c, int&& d, char e. Кортеж — это std::tuple<char, char, int, float, float>, и он устроен следующим образом:tuple_type{std::move(b), e, std::move(d), a, c}.

Рассмотрим структуру, определенную ниже, и предположим, что метафункция deduce_reordered_tuple_typeуже реализована. Как бы вы написали конструктор, чтобы он работал так, как задумано? Если вы считаете, что код для deduce_reodered_tuple_typeбудет вам полезен, я могу его предоставить; это немного долго.

template <class... Args> struct foo
{
    // Assume that the metafunction deduce_reordered_tuple_type is defined.
    typedef typename deduce_reordered_tuple_type<Args...>::type tuple_type;
    tuple_type t_;

    foo(Args&&... args) : t_{reorder_and_forward_parameters<Args>(args)...} {}
};

Редактировать 1 Техника, которую я описал выше, имеет приложения в математических структурах, которые активно используют шаблоны выражений, вариативные шаблоны и метапрограммирование для выполнения агрессивного встраивания. Предположим, вы хотите определить оператор, который принимает произведение нескольких выражений,каждый из которых может быть передан по ссылке, ссылке на const или ссылке rvalue. (В моем случае выражения представляют собой таблицы условной вероятности, а операция — произведение множителей, но что-то вроде матричного умножения также подходит.)

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

  1. Другие выражения могут использовать унифицированный синтаксис для доступа к элементам данных из этого выражения, поскольку вся тяжелая -работа по метапрограммированию выполняется заранее, внутри класса.
  2. Мы можем сэкономить место в стеке, сгруппировав указатели вместе и сохранив более крупные выражения ближе к концу кортежа.
  3. Реализация определенных типов запросов становится намного проще (, например. проверить, является ли какой-либо из указателей, хранящихся в кортеже, псевдонимом данного указателя ).

Большое спасибо за Вашу помощь!

10
задан void-pointer 3 July 2012 в 00:43
поделиться