在struct中初始化数组

时间:2018-05-14 06:43:49

标签: c++ templates initialization

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

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");

4 个答案:

答案 0 :(得分:4)

一般的解决方案是为数组提供一个特殊的构造函数(当T是一个数组时启用),它将源数组复制到struct的数组中。它可以工作,但丢弃数组的移动语义。

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

live demo

如果有时需要T const为非数组,如果value_type不是T,则T定义为std::remove_const_t<T>数组,否则为 if (this.props.dataState.loaded){ data = this.props.data.content; } else { this.renderLoading(); } return( ...

答案 1 :(得分:1)

我建议将所有智能放入make_A,将C阵列转换为std::array<>,以便A<>只需要使用常规类型:

namespace detail {
    template<typename T, std::size_t... Is>
    constexpr std::array<T, sizeof...(Is)> to_std_array(T const* const p,
                                                        std::index_sequence<Is...>)
    {
        return {{p[Is]...}};
    }
}

template<typename T>
A<std::decay_t<T>> make_A(T&& x) {
    return {std::forward<T>(x)};
}

template<typename T, std::size_t N>
A<std::array<T, N>> make_A(T const (& x)[N]) {
    return {detail::to_std_array(x, std::make_index_sequence<N>{})};
}

Online Demo

如果您特别关注硬编码的C字符串(通常与C阵列相反),请考虑转换为string_view类型而不是std::array<>以节省一些空间。

答案 2 :(得分:0)

如果您想要专门为C-Strings实现特殊行为,您可以添加一种特殊处理:

{{1}}

答案 3 :(得分:-1)

使用 std :: decay 它可以工作:

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