2013-12-05 2 views
1

Пусть у меня естьКак построить объект из данных, упакованных в кортеж?

struct SomeType { 
    template<typename... Args> 
    SomeType(Args... args); 
    // ... 
}; 

template<typename... Args> std::tuple<Args> data; // syntax correct? 

и хочу построить новый объект SomeType из значений аргументов, упакованных в tupledata. Как я могу это сделать?

unique_ptr<SomeType> p = new SomeType(data ???); // how? 

редактировать 1 Я думал, что вопрос был довольно ясен, но Кевин не согласен ... Я хочу, чтобы вызвать конструктор SomeBody со значениями, упакованных в tupledata в качестве аргументов. Получил это, Кевен?


редактировать 2 Я думал вопрос вопрос, но Кевин опять не согласен. Для его пользы здесь используется прецедент: я хочу динамически строить поточно-локальные объекты, каждая из которых построена по потоку из некоторых аргументов, предоставленных ранее. Рассмотрим

template<typename Object> 
class thread_specific 
{ 
public: 
    // default constructor: objects will be default constructed 
    thread_specific(); 
    // objects will be copy constructed from specimen provided 
    thread_specific(Object const&specimen); 
    // objects will be constructed from arguments provided 
    template<typename... Args> 
    thread_specifiv(Args... args); 
    // return thread-specific object; objects are constructed only when needed 
    Object& local_object(); 
}; 

(реализована, скажем, через std::map<std::thread::id,unique_ptr<Object>>). Теперь, если глобальный объект thread_specific<> создается пользователем с использованием 3-го конструктора, аргументы должны быть как-то сохранены и переданы в конструктор Object, когда это необходимо, то есть при первом вызове thread_specific<>::local_object() на каждом std::thread.

+0

Вы хотите сделать копию кортежа? Тот же материал, другое имя? Вы хотите ввести typedef или что вы хотите сделать? Знание того, как оно будет использоваться, вероятно, поможет. –

+3

related: http://stackoverflow.com/questions/7858817/unpacking-a-tuple-to-call-a-matching-function-pointer или http://stackoverflow.com/questions/687490/how-do-i -expand-a-tuple-into-variadic-template-functions-arguments –

+0

@NateKohl да, я это видел. Нет принятого ответа. Ответ с наивысшим рангом использует некоторую рекурсию. Интересно, можно ли это сделать быстрее и/или если стандарт обеспечивает определенную поддержку. – Walter

ответ

4

Используйте index_sequence распаковать std::tuple (или std::pair, std::array, или что-нибудь еще поддерживает интерфейс кортежа):

#include <utility> 
#include <tuple> 

template <typename Tuple, std::size_t... Inds> 
SomeClass help_make_SomeClass(Tuple&& tuple, std::index_sequence<Inds...>) 
{ 
    return SomeClass(std::get<Inds>(std::forward<Tuple>(tuple))...); 
} 

template <typename Tuple> 
SomeClass make_SomeClass(Tuple&& tuple) 
{ 
    return help_make_SomeClass(std::forward<Tuple>(tuple), 
     std::make_index_sequence<std::tuple_size<Tuple>::value>()); 
} 

std::index_sequence и std::make_index_sequence будет в C++ 1y. Если вы не можете найти заголовок, который определяет их, вы могли бы использовать эти:

template <std::size_t... Inds> 
struct index_sequence { 
    static constexpr std::size_t size() 
    { return sizeof...(Inds); } 
}; 

template <std::size_t N, std::size_t... Inds> 
struct help_index_seq { 
    typedef typename help_index_seq<N-1, N-1, Inds...>::type type; 
}; 

template <std::size_t... Inds> 
struct help_index_seq<0, Inds...> { 
    typedef index_sequence<Inds...> type; 
}; 

template <std::size_t N> 
using make_index_sequence = typename help_index_seq<N>::type; 

Живой пример, в режиме C++ 11: http://coliru.stacked-crooked.com/a/ed91a67c8363061b

Смежные вопросы