【问题标题】:std::array derived class aggregate initializationstd::array 派生类聚合初始化
【发布时间】:2018-08-13 11:18:38
【问题描述】:

我正在制作一个派生自std::array 的小助手类。很明显,构造函数不继承,它负责大括号初始化;例如:

template<typename T, size_t size>
struct foo : std::array<T,size>
{
     foo(int a, int b)
     : std::array<T,size>{a,b}
     {
          //nothing goes here since constructor is just a dummy that 
          //forwards all arguments to std::array constructor
     }
}

int main()
{
     foo<int,2> myobj = {1,2}; //brace initialization calls custom constructor with inner elements as arguments
}

参数的数量必须完全匹配,所以我倾向于在构造函数中使用可变参数函数参数(因为我不仅每次都在数组中使用 2 个元素)。使用它,我将如何将可变参数包转发给 std::array 构造函数?我对其他允许转发到std::array 构造函数的大括号初始化方法持开放态度。

注意:std::initializer_list 需要运行时初始化,我正在寻找与编译时间/constexpr 兼容的方法。谢谢。

【问题讨论】:

  • 我质疑派生自std::array 的前提。虽然这与问题无关,但您应该知道从std 容器继承的是not a good idea

标签: c++ c++11 templates variadic-templates aggregate-initialization


【解决方案1】:

您可以使用完美转发构造函数:

template<class... U>
foo(U&&... u)
    : std::array<T, size>{std::forward<U>(u)...}
{}

【讨论】:

  • 谢谢,这很好用。我还想补充一下(对于这个问题的未来读者),这会导致 GCC 5.1(我正在使用的版本)出现编译错误,但在 GCC 6.0 及更高版本中可以完美运行。
【解决方案2】:

我不认为从标准容器继承是个好主意。

无论如何...

您可以使用可变参数模板、完美转发以及 SFINAE 来强制参数的数量恰好是 size

您还可以将constexpr 设为foo 构造函数,这样您就可以创建constexpr foo 对象。

举例

#include <array>
#include <type_traits>

template <typename T, std::size_t S>
struct foo : public std::array<T, S>
 {
   template <typename ... As,
             typename std::enable_if<sizeof...(As) == S>::type * = nullptr>
   constexpr foo (As && ... as)
      : std::array<T, S>{ { std::forward<As>(as)... } }
    { }
 };

int main ()
 {
   //constexpr foo<int, 2u> myobj1 = {1}; // compilation error
   constexpr foo<int, 2u> myobj2 = {1, 2}; // compile
   //constexpr foo<int, 2u> myobj3 = {1, 2, 3}; // compilation error
 }

【讨论】:

    猜你喜欢
    • 2015-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-05
    • 2012-02-10
    • 1970-01-01
    • 2016-09-12
    相关资源
    最近更新 更多