首页 > 解决方案 > 在结构中初始化数组

问题描述

假设我们有一些模板结构,有时它的模板应该是一个数组。如何在结构中初始化数组?

template<typename T>
struct A {
    T x;
    A(T x) : x(x) {}
};


int a[6];
A<decltype(a)> b(a);

编译时产生错误:

error: array initializer must be an initializer list
A(T x) : x(x) {}
         ^

UPD1。这个东西使用的更完整的代码:

template<typename T>
struct A {
    T x;
    A(const T& x) : x(x) {}
    A(const T&& x) : x(std::move(x)) {}
};

template<typename T>
A<typename std::remove_reference<T>::type> make_A(T&& a) {
    return A<typename std::remove_reference<T>::type>(std::forward<T>(a));
}


auto a = make_A("abacaba");

标签: c++templatesinitialization

解决方案


一个通用的解决方案是为数组提供一个特殊的构造函数(当T是数组时启用),它将源数组复制到结构的数组。它有效,但丢弃了数组的移动语义。

#include <iostream>
#include <type_traits>
#include <string>
#include <tuple>

template<typename T>
struct A {
    using value_type = std::remove_const_t<T>;
    value_type x;

    template<class U=T> A(const T&  src, std::enable_if_t<!std::is_array_v<U>, int> = 0) : x(src) {}
    template<class U=T> A(const T&& src, std::enable_if_t<!std::is_array_v<U>, int> = 0) : x(std::move(src)) {}
    template<class U=T> A(const T&  src, std::enable_if_t< std::is_array_v<U>, int> = 0) { std::copy(std::begin(src), std::end(src), std::begin(x)); }
};

template<typename T>
auto make_A(T&& a)
{ return A<typename std::remove_reference_t<T>>(std::forward<T>(a)); }

int main()
{
    auto a1 = make_A("the answer");
    std::ignore = a1;
    auto a2 = make_A(42);
    std::ignore = a2;
}

现场演示

如果您有时需要T用于const非数组,则改进将定义value_typeT好像T不是数组,std::remove_const_t<T>否则定义为非数组。


推荐阅读