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++ 基于可变模板的通用聚合初始化_C++_Templates_C++11_C++14_Variadic Templates - Fatal编程技术网

C++ 基于可变模板的通用聚合初始化

C++ 基于可变模板的通用聚合初始化,c++,templates,c++11,c++14,variadic-templates,C++,Templates,C++11,C++14,Variadic Templates,这是一个有趣的问题,我刚才还在想。 给定具有基础聚合的结构: #include <array> template <typename T, size_t N> struct A { constexpr A() = default; template <typename ... Ts> constexpr A(const T& value, const Ts& ... values); // magic std::a

这是一个有趣的问题,我刚才还在想。 给定具有基础聚合的
结构

#include <array>

template <typename T, size_t N>
struct A
{
   constexpr A() = default;

   template <typename ... Ts>
   constexpr A(const T& value, const Ts& ... values); // magic

   std::array<T, N> arr; // aggregate
};

这里有一种方法是有效的,但几乎可以肯定会有所改进

我们有一个
a
的构造函数,它接受一个参数包,将每个元素转换成一个元组,将元组连接在一起形成一个大元组,然后简单地使用该大元组的聚合初始化。以下所有内容都可以是
constexpr
,为了简洁起见,我省略了它

首先,我们进行转换:

template <class... Us>
A(Us const&... us)
: A(std::tuple_cat(as_tuple(us)...))
{ }
模板
A(美国常数和…美国)
:A(std::tuple\u cat(as\u tuple(us)…)
{ }
与:

//单参数
模板
自动作为元组(常量和单位){
return std::forward_as_tuple(u);
}
//聚合参数
模板
自动作为元组(常量和A){
以元组形式返回(a,std::make_index_sequence{});
}
模板
自动作为元组(常量和A,标准::索引序列){
返回std::forward_as_tuple(std::get(a.arr)…);
}
然后我们从这里开始初始化:

template <class... Us, class = std::enable_if_t<(sizeof...(Us) <= N)>>
A(std::tuple<Us...> const& t)
: A(t, std::index_sequence_for<Us...>{})
{ }

template <class... Us, size_t... Is>
A(std::tuple<Us...> const& t, std::index_sequence<Is...> )
: arr{{std::get<Is>(t)...}}
{ }

template巴里的回答肯定是正确的,可以接受。但它需要添加一些C++14库(您也可以自己用C++11编写),并且总体上需要一些好的
tuple
-和元编程

让我们将多个参数视为“范围的范围”,其中范围只是一个指针和一个大小。标量参数只是大小1范围,而
a
参数是size-N范围

template<class T>
struct Range
{
    T const* data_;
    std::size_t size_;

    constexpr T const* begin() const noexcept { return data_; }
    constexpr T const* end() const noexcept { return data_ + size_; }
    constexpr std::size_t size() const noexcept { return size_; }
};

template<class T>
constexpr Range<T> as_range(T const& t)
{
    return { &t, 1 };
}

template<class T, std::size_t N>
struct A;

template<class T, std::size_t N>
constexpr Range<T> as_range(A<T, N> const& a)
{
    return { a.arr, N };    
}
模板
结构范围
{
T常数*数据;
标准:尺寸;
constexpr T const*begin()const noexcept{返回数据}
constexpr T const*end()const noexcept{return data_u+size_;}
constexpr std::size_t size()const noexcept{return size_;}
};
模板
constexpr范围为_范围(T const&T)
{
返回{&t,1};
}
模板
结构A;
模板
constexpr范围作为_范围(常数A)
{
返回{a.arr,N};
}
然后,您可以简单地在所有范围的所有元素上执行双循环

template <typename T, size_t N>
struct A
{
    T arr[N]; // aggregate

    constexpr A() = default;

    template <typename U, typename... Us>
    constexpr A(U const u, Us const&... us)
    : 
        arr{}
    {
        Range<T> rngs[1 + sizeof...(Us)] { as_range(u), as_range(us)... };
        auto i = 0;
        for (auto const& r : rngs)
            for (auto const& elem : r)
                arr[i++] = elem;
        assert(i == N);                
    }
};
模板
结构A
{
T arr[N];//聚合
constexpr A()=默认值;
模板
常数表达式A(U常数U,美国常数和…美国)
: 
arr{}
{
射程RNG[1+sizeof…(Us)]{as_射程(u),as_射程(Us)…};
自动i=0;
用于(自动施工和恢复:rngs)
用于(自动常量和元素:r)
arr[i++]=elem;
断言(i==N);
}
};
在编译时工作(需要GCC>=6.0或Clang>=3.4)

模板
无效打印(A常量和A){
对于(T const&T:a.arr){

std::cout在
ay(1,2)中
y[2]
的预期值是多少;
?构造函数调用的运行时开销如何?@VaughnCato感谢您的捕获,这是一个错误类型,已更新now@WojciechFrohmbergconstexpr意味着内联,所以我们不能谈论调用。我要添加的唯一一件事是使用
forward\u as\u tuple
来减少复制更容易理解(由于没有模板元编程),“不引入任何运行时开销”规范丢失。@black,谢谢,FTFY。请注意,这需要将数据成员从
std::array
更改为
T[N]
C-array,因为非常量
运算符[]前者的
不是
constexpr
template<class T>
struct Range
{
    T const* data_;
    std::size_t size_;

    constexpr T const* begin() const noexcept { return data_; }
    constexpr T const* end() const noexcept { return data_ + size_; }
    constexpr std::size_t size() const noexcept { return size_; }
};

template<class T>
constexpr Range<T> as_range(T const& t)
{
    return { &t, 1 };
}

template<class T, std::size_t N>
struct A;

template<class T, std::size_t N>
constexpr Range<T> as_range(A<T, N> const& a)
{
    return { a.arr, N };    
}
template <typename T, size_t N>
struct A
{
    T arr[N]; // aggregate

    constexpr A() = default;

    template <typename U, typename... Us>
    constexpr A(U const u, Us const&... us)
    : 
        arr{}
    {
        Range<T> rngs[1 + sizeof...(Us)] { as_range(u), as_range(us)... };
        auto i = 0;
        for (auto const& r : rngs)
            for (auto const& elem : r)
                arr[i++] = elem;
        assert(i == N);                
    }
};
template <class T, size_t N>
void print(A<T, N> const& a) {
    for (T const& t : a.arr) {
        std::cout << t << ' ';
    }
    std::cout << '\n';
}

int main()
{
    constexpr A<int, 3> x(1, 2, 3);
    constexpr A<int, 2> y(1, 2);

    constexpr A<int, 6> a(x, 1, 2, 3);
    constexpr A<int, 6> b(1, x, 2, 3);
    constexpr A<int, 6> c(1, 2, x, 3);
    constexpr A<int, 6> d(1, 2, 3, x);
    constexpr A<int, 6> e(x, x);
    constexpr A<int, 6> f(y, y, y);

    print(a); // 1 2 3 1 2 3
    print(b); // 1 1 2 3 2 3
    print(c); // 1 2 1 2 3 3 
    print(d); // 1 2 3 1 2 3
    print(e); // 1 2 3 1 2 3
    print(f); // 1 2 1 2 1 2    
}