Я столкнулся с необходимостью изменить порядок вариативного списка параметров, который предоставляется конструктору структуры. После переупорядочения в зависимости от их типов параметры будут храниться в виде кортежа. Мой вопрос в том, как это можно сделать, чтобы современный компилятор 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, скопировать выражения, переданные по ссылке, в константу и взять адреса выражений, переданных по ссылке. Использование техники, которую я описал выше, дает несколько преимуществ.
Большое спасибо за Вашу помощь!