Я столкнулся с необходимостью переупорядочивать вариационный список параметров, который предоставляется конструктору структуры. После переупорядочения на основе их типов параметры будут сохранены в виде кортежа. Мой вопрос заключается в том, как это можно сделать, чтобы современный компилятор С++ (например, g++-4.7
) не генерировал ненужные инструкции по загрузке или хранению. То есть, когда конструктор вызывается со списком параметров переменного размера, он эффективно подталкивает каждый параметр на место на основе упорядочения по типам параметров.
Вот конкретный пример. Предположим, что базовый тип каждого параметра (без ссылок, ссылок rvalue, указателей или квалификаторов) - это char
, int
или float
. Как я могу сделать это так, чтобы сначала отображались все параметры базового типа char
, а затем все из базового типа int
(что оставляет параметры базового типа float
последним). Относительный порядок, в котором были заданы параметры, не должен нарушаться внутри подмножеств однородного базового типа.
Пример: foo::foo()
вызывается с аргументами float a, char&& b, const float& c, int&& d, char e
. Кортеж tupe 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 Техника, описанная выше, имеет приложения в математических рамках, которые сильно используют шаблоны выражений, вариационные шаблоны и метапрограммирование для выполнения агрессивной вставки. Предположим, что вы хотите определить оператор, который принимает произведение нескольких выражений, каждое из которых может быть передано по ссылке, ссылка на константу или ссылку rvalue. (В моем случае выражения являются условными таблицами вероятности, а операция является факторным продуктом, но что-то вроде матричного умножения работает соответственно.)
Для оценки продукта вам необходим доступ к данным, предоставленным каждым выражением. Следовательно, вы должны перемещать выражения, переданные как ссылки rvalue, копировать выражения, переданные по ссылке на const, и принимать адреса выражений, переданных по ссылке. Используя описанную выше технику, вы получаете несколько преимуществ.
- Другие выражения могут использовать единообразный синтаксис для доступа к элементам данных из этого выражения, поскольку все тяжелые работы метапрограммирования выполняются заранее, внутри класса.
- Мы можем сохранять пространство стека, группируя указатели вместе и сохраняя более крупные выражения в конце кортежа.
- Реализация некоторых типов запросов становится намного проще (например, проверьте, не указал ли какой-либо из указателей, сохраненных в алиасах кортежа, заданный указатель).
Большое спасибо за вашу помощь!