【问题标题】:How to list-initialize a const std::array member using a std::array constructor argument C++如何使用 std::array 构造函数参数 C++ 对 const std::array 成员进行列表初始化
【发布时间】:2019-04-28 18:27:05
【问题描述】:

假设我们在 C++11 或更高版本中有以下类:

class MyClass {
private:
    const std::array<SomeType, 100> myArray;
public:
    explicit MyClass(std::array<SomeOtherType, 100> initArray);
};

假设 SomeType 类有一个以单个 SomeOtherType 作为参数的构造函数,是否可以在构造函数中使用列表初始化来初始化 const 成员数组?这样做的语法是什么?

显然,像这样直接初始化它是行不通的:

MyClass::MyClass(std::array<SomeOtherType, 100> initArray) :
    myArray{initArray} {}

谢谢!

【问题讨论】:

  • 您知道您的具有 const 成员的类不可复制吗?
  • 如果您使用的是 c++11(或更高版本),请查找 std::initializer_list 的文档。如果您使用 GCC 进行编译,您可能还会发现这篇文章很有用 stackoverflow.com/questions/8192185/…
  • @Swordfish:感谢您的提醒——这对我当前的用例来说应该不是问题,但我会牢记这一点以备不时之需。
  • @HappyKeyboard:谢谢,我会看看 std::initializer_list。也很高兴知道 std::array 和 gcc 需要双花括号!

标签: c++ constructor constants stdarray list-initialization


【解决方案1】:

您可以使用可变参数模板:

#include <array>

struct foo
{
    const std::array<int, 10> bar;

    template<typename... T>
    foo(T&&... t)
    : bar({ std::move(t)... })
    {}
};

int main()
{
    foo f{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
}

或者您可以使用传递给构造函数的数组对其进行初始化:

#include <array>

struct foo
{
    const std::array<int, 10> bar;

    explicit foo(std::array<int, 10> const &qux)
    : bar{ qux }
    {}
};

int main()
{
    std::array<int, 10> qux;
    foo f(qux);
}

但是这些选项没有考虑到您希望将SomeOtherType 的数组转换为SomeType 的数组。起初我没有意识到,上面的变种。

#include <cstddef>
#include <array>
#include <utility>

struct SomeOtherType{};

struct SomeType {
    SomeType(SomeOtherType) {}
};

struct MyClass
{
    const std::array<SomeType, 100> myArray;

    template<typename T, std::size_t... N>
    MyClass(T&& qux, std::index_sequence<N...>)
    : myArray{ qux[N]... }
    {}

    explicit MyClass(std::array<SomeOtherType, 100> const &qux)
    : MyClass{ qux, std::make_index_sequence<100>{} }
    {}
};

int main()
{
    std::array<SomeOtherType, 100> qux{};
    MyClass foo(qux);
}

【讨论】:

    【解决方案2】:

    您可以使用 std::index_sequence 和委托构造函数解包参数

    template<typename Arr, size_t... Is>
    MyClass(Arr&& arr, std::index_sequence<Is...>)
      : myArray{arr[Is]...} ()
    
    explicit MyClass(std::array<SomeOtherType, 100> arr) : MyClass(arr, std::make_index_sequence<100>{}) ()
    

    【讨论】:

      【解决方案3】:

      这是可能的。您只需要一个小辅助函数模板来为您进行转换。像这样的:

      template <class T, class U, size_t N>
      std::array<T, N> ArrayConvert(std::array<U, N> const& init)
      {
        std::array<T, N> result;
        std::copy(init.begin(), init.end(), result.begin());
        return result;
      }
      
      class Foo
      {
        std::array<int, 100> myArray;
      public:
        template <class U> Foo(std::array<U, 100> const& init)
          : myArray(ArrayConvert<int>(init))
        {
        }
      };
      

      【讨论】:

        猜你喜欢
        • 2015-09-04
        • 2022-01-22
        • 1970-01-01
        • 2014-02-27
        • 1970-01-01
        • 2011-10-17
        • 2017-04-17
        • 1970-01-01
        相关资源
        最近更新 更多