簡體   English   中英

在struct中初始化數組

[英]Initializing array in struct

假設我們有一些模板化的結構, 有時它的模板應該是一個數組。 如何在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");

一般的解決方案是為數組提供一個特殊的構造函數(當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;
}

現場演示

如果有時需要T為非數組的const ,那么改進就是將value_type定義為T如果T不是數組),否則定義為std::remove_const_t<T>

我建議將所有make_A放入make_A ,將C數組轉換為std::array<> s,以便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>{})};
}

在線演示

如果您只關注硬編碼的C字符串(通常與C數組相反),請考慮轉換為string_view類型而不是std::array<>以節省一些空間。

如果它是您想要專門為C-Strings實現的特殊行為,您可以添加一個特殊處理:

// for all non-C-string cases
template<typename T, std::enable_if_t<!std::is_same_v<std::decay_t<T>, const char*>>* = nullptr>
A<typename std::remove_reference<T>::type> make_A(T&& a) {
    return A<typename std::remove_reference<T>::type>(std::forward<T>(a));
}

// in case a C-string got passed
A<std::string> make_A(const std::string& str) {
    return A<std::string>(str);
}

int main()
{
    auto a = make_A("abacaba");
    auto b = make_A(5);
}

使用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));
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM