【问题标题】:Is there a particular syntax for initializing an std::array from another, different std::array?是否有从另一个不同的 std::array 初始化 std::array 的特定语法?
【发布时间】:2013-04-22 10:06:04
【问题描述】:

我有这种情况:

class A {
    ...
};

class B {
    public:
        B(A x) { .... }
}

std::array<A, some_constant_value> init;
std::array<B, some_constant_value> arr = {
    init[0], 
    init[1],
    init[2],
    ...... ,
    init[some_constant_value-1]
};

有没有比这更好的语法来避免键入所有元素? (这不需要干预 some_constant_value 会改变的可能性吗?)

【问题讨论】:

  • 需要初始化还是可以走简单的路线做作业?
  • @Pubby 不幸的是,我无法完成分配,因为 B 不会在没有参数的情况下构造。

标签: c++ arrays stl initialization


【解决方案1】:

我有这段代码。我想这就是你想要的:

  template<unsigned... Indices>
  struct indices {
    using next = indices<Indices..., sizeof...(Indices)>;
  };

  template<unsigned N>
  struct build_indices {
    using type = typename build_indices<N-1>::type::next;
  };
  template<>
  struct build_indices<0> {
    using type = indices<>;
  };

  namespace impl {
    template<typename To, typename From, unsigned... Is>
    std::array<To, sizeof...(Is)>
    array_convert_impl(std::array<From, sizeof...(Is)> const& from, indices<Is...>) {
      return std::array<To, sizeof...(Is)>{{ from[Is]... }}; 
    }
  } // namespace impl
  template<typename To, typename From, unsigned N>
  std::array<To, N>
  array_convert(std::array<From, N> const& from) {
    return impl::array_convert_impl<To>(from, typename build_indices<N>::type());
  }

那么你可以这样做:

std::array<B, some_constant_value> arr = array_convert<B>(init);

【讨论】:

  • 天哪,它有效!一旦我理解了整个事情,我会接受这个作为答案,谢谢。
  • @Svalorzen 对缺乏解释表示歉意。如果您在理解某些部分时需要帮助,那就问吧。
  • 您可以通过删除 array_convert 的无用前向声明,删除显式转换为 To(OP 正在执行隐式)并在示例中使用 auto 来减少它。少说几句话应该少花几秒钟才能理解;-)
  • @Pubby 我想我明白了一般的想法,但更详细的解释会很好。我知道build_index 创建了某种整数列表来访问然后扩展的原始数组,但我不确定递归过程是如何工作的。
  • @Pubby 此外,你能告诉我一般使用它有多安全吗?是否存在编译器可能没有注意到错误用法并因此导致运行时崩溃的情况? (虽然我不这么认为,因为它是在编译时扩展的)
【解决方案2】:

标准库提供的另一种解决方案是:

std::array<B, some_constant_value> 
arr((std::copy(init.begin(),init.end(),(&arr)->begin()),arr));

注意构造函数的参数是用((...))括起来的,所以它 被正确解析为逗号表达式而不是两个参数。

此解决方案依赖于 B 可以隐式构造的事实 A。如果转换构造函数是,一个简短的解决方案也将起作用 明确的是:

auto lamb = 
[&init]() -> B { static size_t i = 0; return B(init[i++]); };  
std::array<B, some_constant_value> 
arr((std::generate((&arr)->begin(),(&arr)->end(),lamb),arr));

以下测试程序,使用 GCC 4.7.2、clang 3.2 和 Intel C++ 13.1.1 构建, (options -g -O0 -Wall -std=c++11) 说明了这两种解决方案:

#include <iostream>
#include <array>
#include <algorithm>

struct A 
{
    int _i = 42;
};

struct B 
{
    B(A x) 
    : _i(x._i){}
    int _i; 
};

struct C 
{
    explicit C(A x) 
    : _i(x._i){}
    int _i; 
};

using namespace std;

int main()
{
    array<A, 10> init;
    array<B, 10> arr((copy(init.begin(),init.end(),(&arr)->begin()),arr));
    cout << "arr contains..." << endl;
    for (size_t i = 0; i < arr.size(); ++i) {
        cout << arr[i]._i << endl;
    }
    auto lamb = 
    [&init]() -> C { static size_t i = 0; return C(init[i++]); };  
    array<C, 10> brr((generate((&brr)->begin(),(&brr)->end(),lamb),brr));
    cout << "brr contains..." << endl;
    for (size_t i = 0; i < brr.size(); ++i) {
        cout << brr[i]._i << endl;
    }
    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-05
    • 2012-02-10
    • 2023-02-06
    • 2021-03-19
    • 1970-01-01
    • 2021-06-26
    • 2012-03-08
    • 2013-08-20
    相关资源
    最近更新 更多