2016-07-29 2 views
4

Я пытаюсь использовать шаблоны в C++, чтобы сделать следующее:Замена типа внутри кортежа в C++ 11

У меня есть функция, как это:

template<typename... Args> 
void f1(const std::tuple<Args...>& t1); 

Внутри этой функции, Я хотел бы создать еще один набор t2, так что каждый элемент t1 будет скопирован в t2 в том же положении, за исключением элементов типа A, для которых t2 должен создать объект типа B.

Однако конструктор B принимает ссылку на объект типа A, а также - второй аргумент типа C&. Экземпляр C создается перед преобразованием и должен передаваться как второй аргумент конструктору B всякий раз, когда встречается объект типа A.

Нечто подобное, только полностью обобщается:

std::tuple<int, B, double, B> Convert(std::tuple<int, A, double, A> tpl, C& c) 
{ 
    return std::tuple<int, B, double, B>(
    std::get<0>(tpl), 
    B(std::get<1>(tpl), c), 
    std::get<2>(tpl), 
    B(std::get<3>(tpl), c), 
); 
} 
+2

Хорошо, а с какой проблемой вы столкнулись? SO не является бесплатным местом аутсорсинга. –

+0

Я не зашел очень далеко; в других местах моего кода мне приходилось писать код шаблона, который манипулирует кортежами, например, применяя функцию, беря серию аргументов в кортеж, содержащий поля тех же типов, что и аргументы (делая обратное, то есть преобразовывая ряд аргументы в кортеж, это просто), поэтому я продолжаю пытаться найти способ сделать это, полагая, что мне дан кортеж t1, или что у меня есть ряд аргументов, но я никуда не хожу ... – sunmat

+0

Если бы этого глупого элемента 'C &' не было, это было бы относительно легко метапрограммировать (если у вас есть доступ к C++ 14, конечно). Но поскольку это ограничение существует, оно становится безумно трудным, так как выражения, которые вы используете для построения каждого значения, теперь * разные *, в зависимости от типа этого значения. Вы должны найти способ нормализовать выражение, которое требует создания 'tuple'-in-a-'tuple' или чего-то еще. –

ответ

3

Примечание: Новый вопрос просит чего-то более сложного. Оставляя этот ответ тем, кто мог бы выиграть.

Сила шаблона условными и расширения шаблона пакета:

template<typename... Args> 
void f1(const std::tuple<Args...>& t1) { 
    std::tuple<typename std::conditional< 
     std::is_same<A, Args>::value, B, Args>::type...> t2(t1); 
    // Both Args are expanded in parallel, resulting in the same types 
    // Do things with t2 
} 
+0

Спасибо, это начало, но я забыл упомянуть, что конструктор B принимает const A & и другой аргумент; как я могу передать 2-й аргумент конструктору? – sunmat

+0

Я отредактировал мой вопрос. Благодарю. – sunmat

+0

@sunmat: Это другой и более сложный вопрос. Однако можно сделать все. – Deduplicator

1

Я предполагаю, что это позволит решить проблему:

#include<functional> 
#include<tuple> 
#include<cassert> 

struct A {}; 
struct C {}; 
struct B { B(const A &, C &) {} }; 

template<typename T> 
T g(const T &t, C &) { return t; } 

B g(const A &a, C &c) { 
    return B{a, c}; 
} 

template<std::size_t... I, typename... Args> 
void f(const std::tuple<Args...> &tup,std::index_sequence<I...>) { 
    C c; 
    auto val = std::make_tuple(g(std::get<I>(tup), c)...); 
    assert((std::is_same<std::tuple<C, B, C>, decltype(val)>::value)); 
} 

template<typename... Args> 
void f(const std::tuple<Args...> &tup) { 
    f(tup, std::make_index_sequence<sizeof...(Args)>()); 
} 

int main() { 
    auto tup = std::make_tuple(C{}, A{}, C{}); 
    f(tup); 
} 

Обратите внимание, что это решение требует C++ 14, в основном из-за std::make_index_sequence и std::index_sequence.
Вы можете найти подходящую для них версию C++ 11 онлайн, если это необходимо.

+0

Вы можете выделить отображение в отдельной функции, которая просто вызывается 'f' с соответствующим отображением (определяется в локальном классе). – Deduplicator

+0

@Deduplicator Да, это минимальный рабочий пример. Я не знаю, как структурировать код, потому что я не знаю, что такое реальный мир. – skypjack