Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何编写类似于std::make_元组的make_向量?_C++_Templates_C++11_Variadic Templates_Perfect Forwarding - Fatal编程技术网

C++ 如何编写类似于std::make_元组的make_向量?

C++ 如何编写类似于std::make_元组的make_向量?,c++,templates,c++11,variadic-templates,perfect-forwarding,C++,Templates,C++11,Variadic Templates,Perfect Forwarding,而不是像这样创建向量: std::vector<int> v1{1,2,3}; std::vector<double> v2{1.1,2.2,3.3}; std::vector<Object> v3{Object{},Object{},Object{}}; 与和类似,这里是我对向量的尝试: #include <iostream> #include <vector> #include <utility&

而不是像这样创建向量:

  std::vector<int>     v1{1,2,3};
  std::vector<double>  v2{1.1,2.2,3.3};
  std::vector<Object>  v3{Object{},Object{},Object{}};  
与和类似,这里是我对向量的尝试:

#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)...};
}

m.cpp:auto make_vector(T&&…[with T={int,int,int}]的实例化中:
m、 cpp:16:30:从这里开始需要
m、 cpp:8:78:错误:对不完整类型“class std::tuple_element”的使用无效
使用first_type=typename std::tuple_元素::type;
^
在m.cpp中包含的文件中:3:0:
/usr/include/c++/5/utility:85:11:注意:“class std::tuple_元素”的声明
类元组元素;
^
m、 cpp:9:60:错误:不完整类型“class std::tuple_element”的使用无效
返回std::vector{std::forward(args)…..};
^
在m.cpp中包含的文件中:3:0:
/usr/include/c++/5/utility:85:11:注意:“class std::tuple_元素”的声明
类元组元素;
^
m、 cpp:在函数“int main()”中:
m、 cpp:16:30:错误:“void v1”的类型不完整
自动v1=生成向量(1,2,3);
如何制作通用例程,
使用第一个参数的第一种类型来实例化向量?

如何将参数作为初始值转发给向量?

就像您所做的那样-gcc和msvc都使用一个微小的
#include
编译您的函数,因为您无论如何都不能使用它来创建空向量,我们可以通过提供一个额外的模板参数来避免
元组
依赖关系:

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)...
    };
}
模板
自动生成向量(T0&&first,Ts&&args)
{
使用第一种类型=标准::衰减;
返回std::vector{
标准::向前(第一),
标准::转发(args)。。。
};
}
如果
第一个
作为左值传入,则它还有额外的工作优势

让我们跟随的是,允许用户明确指定返回类型,或者使用由
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{ ((void)ret.emplace_back(std::forward<Ts>(args)), 0)..., 0 };
    return ret;
}
模板结构标识{using type=T;};
模板
struct-ret:identity{};
模板
struct ret:std::common_type{};
模板
使用ret_t=typename ret::type;
模板
std::vector make_vector(Ts&&…args){
std::载体ret;
净储量(面积…(args));
使用expander=int[];
(void)扩展器{((void)ret.emplace_back(std::forward(args)),0)…,0};
返回ret;
}
使用完美转发意味着您希望消除不必要的复制;这与使用
initializer\u list
构造函数不一致,后者需要每个元素的副本。因此,相反,上面的代码
保留
s适当的空间量,然后
使用通常的包扩展技巧逐个放置元素


如果您不想启用显式转换,则可以使用
push_back
,这可能会导致类型不匹配。然而,在这种情况下,该类型要么由用户显式指定,要么由
公共类型
通过隐式转换推导,因此
放置回
可能很好。

@Pixelchemist wow。。。完全正确。感谢这是与其他
make_vector
实现相比更好的解决方案,因为它还支持仅移动类型。非常感谢你!这不适用于自定义类,如
explicit FieldInfo(const std::string&name,const char id,const int len,const bool是必需的)
我这样调用
auto temp=make_vector((“Serial Num”,'S',50,true),(“Customer”,'C',18,true)
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);  
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)...
    };
}
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{ ((void)ret.emplace_back(std::forward<Ts>(args)), 0)..., 0 };
    return ret;
}