1

Вместо создания векторов, как это:Как написать make_vector, похожий на std :: make_tuple?

std::vector<int>  v1{1,2,3}; 
    std::vector<double> v2{1.1,2.2,3.3}; 
    std::vector<Object> v3{Object{},Object{},Object{}}; 

Я хотел бы создать их с помощью обобщенной функции:

auto v1 = make_vector(1,2,3); 
    auto v2 = make_vector(1.1,2.2,3.3); 
    auto v3 = make_vector(Object{},Object{},Object{}); 

Подобно std::make_pair и std::make_tuple, здесь была моя попытка для вектора:

#include <iostream> 
#include <vector> 
#include <utility> 

template <typename... T> 
auto make_vector(T&&... args) 
{ 
    using first_type = typename std::tuple_element<0, std::tuple<T...>>::type; 
    return std::vector<first_type>{std::forward<T>(args)...}; 
} 

Она компилирует, но когда я пытаюсь использовать его:

auto vec = make_vector(1,2,3); 

m.cpp: In instantiation of ‘auto make_vector(T&& ...) [with T = {int, int, int}]’: 
m.cpp:16:30: required from here 
m.cpp:8:78: error: invalid use of incomplete type ‘class std::tuple_element<0ul, std::tuple<int, int, int> >’ 
    using first_type = typename std::tuple_element<0, std::tuple<T...>>::type; 
                      ^
In file included from m.cpp:3:0: 
/usr/include/c++/5/utility:85:11: note: declaration of ‘class std::tuple_element<0ul, std::tuple<int, int, int> >’ 
    class tuple_element; 
     ^
m.cpp:9:60: error: invalid use of incomplete type ‘class std::tuple_element<0ul, std::tuple<int, int, int> >’ 
    return std::vector<first_type>{std::forward<T>(args)...}; 
                  ^
In file included from m.cpp:3:0: 
/usr/include/c++/5/utility:85:11: note: declaration of ‘class std::tuple_element<0ul, std::tuple<int, int, int> >’ 
    class tuple_element; 
     ^
m.cpp: In function ‘int main()’: 
m.cpp:16:30: error: ‘void v1’ has incomplete type 
    auto v1 = make_vector(1,2,3); 

Как я могу сделать общую процедуру,
используется первый тип первого параметра экземпляр вектора?
Как передать аргументы в качестве значений инициализации в вектор?

+1

'#include '? – Pixelchemist

+0

@Pixelchemist ничего себе ... это точно. благодаря –

ответ

1

Как вы сделали - как gcc, так и msvc скомпилируйте свою функцию с помощью крошечного #include <tuple>.

6

Поскольку вы не можете использовать это, чтобы создать пустой вектор в любом случае, мы можем избежать tuple зависимости, просто предоставляя дополнительный аргумент шаблона:

template <class T0, class... Ts> 
auto make_vector(T0&& first, Ts&&... args) 
{ 
    using first_type = std::decay_t<T0>; 
    return std::vector<first_type>{ 
     std::forward<T0>(first), 
     std::forward<Ts>(args)... 
    }; 
} 

, который имеет дополнительное преимущество, если рабочий first был принят в качестве lvalue.

2

Следуйте за нами make_array и разрешите пользователям либо явно указывать тип возврата, либо использовать тип возврата, определенный std::common_type.

template<class T> struct identity { using type = T; }; 
template<class D, class... Ts> 
struct ret : identity<D> {}; 
template<class... Ts> 
struct ret<void, Ts...> : std::common_type<Ts...> {}; 
template<class D, class... Ts> 
using ret_t = typename ret<D, Ts...>::type; 

template<class D = void, class... Ts> 
std::vector<ret_t<D, Ts...>> make_vector(Ts&&... args) { 
    std::vector<ret_t<D, Ts...>> ret; 
    ret.reserve(sizeof...(args)); 
    using expander = int[]; 
    (void) expander{ (ret.emplace_back(std::forward<Ts>(args)), 0)..., 0 }; 
    return ret; 
} 

Использование идеальной пересылки предполагает, что вы хотите устранить ненужное копирование; это не согласуется с использованием конструктора initalizer_list, который требует копии каждого элемента. Таким образом, вместо приведенного выше кода reserve s нужное количество места, а затем emplace_back s элементы поодиночке с обычным трюком расширения пакета. Я опустил перегруженную защиту запятой, так как vector::emplace_back, как известно, возвращает void.

push_back можно использовать вместо этого, если вы не хотите включать явные преобразования за счет потенциального перемещения по несоответствию типа. Однако в этом случае тип либо явно указывается пользователем, либо выводится с помощью неявных преобразований на common_type, поэтому emplace_back может быть в порядке.