【问题标题】:How to parameterize the number of parameters of a constructor?如何参数化构造函数的参数个数?
【发布时间】:2015-09-04 16:38:48
【问题描述】:

我想在模板类构造函数中接受最多多个参数(这个数字在模板参数中定义)。我不能使用initializer_list,因为据我所知,我无法在编译时断言它的大小。

我尝试了什么

我的第一次尝试是使用 std::array 作为参数:

template<size_t s>
class foo {
  int v[s];
public:
  foo(std::array<int, s>) {/*...*/}
};

但是,这迫使我像这样初始化(即使构造函数不是explicit):

foo<4> a{{1,2,3,4}} // Two brackets.

我认为可能有一些模板魔法(可变参数模板?),但我什至无法弄清楚在构造函数中使用的正确语法。我不能递归调用构造函数...可以吗?

我尝试为std::array 寻找构造函数的定义(因为它不允许比数组大小更多的参数,这正是我想要的),但我能找到的只是它具有隐式构造函数.那是默认构造函数吗?如果是这样,如何

std::array<int, 3> a = {1,2,3}

工作?

可选奖励:为什么标准没有定义固定大小的替代std::initializer_list?像std::static_initializer_list&lt;T, N&gt; 这样的东西。未来是否有计划支持此类功能?还需要吗?

【问题讨论】:

  • 为了澄清,你的意思是写std::array&lt;int, s&gt;,对吧?我在任何地方都找不到n。同样std::array 使用aggregate initialization
  • 你在我编辑修复它的那一刻让我:)谢谢你的链接!
  • 用矢量怎么样?
  • 你到底想要什么?你想要大小作为第一个参数吗?还是您希望它自动为您处理?如果你这样做,使用std::vector 和它的大小函数,我想。
  • 当参数少于限制时你打算怎么做?我想知道一个带有默认参数的构造函数是否就足够了。

标签: c++ templates c++11 constructor


【解决方案1】:

您可以创建一个可变参数构造函数并断言它提供了正确数量的参数:

template <size_t SZ>
struct Foo {
    template <typename... Args>
    Foo(Args... args) {
        static_assert(sizeof...(Args) <= SZ, "Invalid number of arguments");
        // ... stuff ...
    }
};

这样:

Foo<3> f;                // OK
Foo<3> f(1, 2, 3);       // OK
Foo<3> f(1, 2, 3, 4, 5); // error

作为初始化数组的示例,可能如下所示:

template <size_t SZ>
struct Foo {
    template <typename... Args>
    Foo(Args... args) 
    : v{{args...}}
    {
        static_assert(sizeof...(Args) <= SZ, "Invalid number of arguments");
    }

    std::array<int, SZ> v;
};

正如您所期望的那样正确构造v,但是如果您尝试将多个SZ args 传递给Foo 的构造函数,您会在@987654328 之前看到初始化v 的错误@。

为了更清晰的static_assert 错误,您可以将顶级Foo 委托给私有构造函数,这些构造函数需要一个额外的integral_constant 参数来判断它们是否是有效的构造函数:

template <typename... Args>
Foo(Args... args)
: Foo(std::integral_constant<bool, sizeof...(Args) <= SZ>{}, 
      args...)
{ }

private:
template <typename... Args>
Foo(std::true_type, Args... args)
: v{{args...}}
{ }

template <typename False, typename... Args>
Foo(False, Args... )
{ 
    // False is only ever std::false_type
    static_assert(False::value, "Invalid number of arguments!");
}

【讨论】:

  • 你将如何“获取”这些参数?
  • 我读到了 OP 的声明“...up to a number of parameters ...”,意思是 OP 想要接受一个 可变个参数,但不超过最大数量。在这种情况下,我认为static_assert 必须使用&lt;= 而不是==
  • @vsoftco 我以为你不必得到它们?你只需 (Args...) 并且当你替换时事情应该会很好,前提是你有正确的构造函数在等待,对吧?
  • @VermillionAzure 我想这取决于情况。假设您想使用构造函数的参数在 OPs 代码中初始化数组 v。如果在 Args... 类型传递上没有某种递归/模式匹配,你将如何做到这一点?
  • @vsoftco 改为 std::array&lt;int, SZ&gt; v,然后只需 v({{args...}}) 就可以了。
猜你喜欢
  • 1970-01-01
  • 2022-09-23
  • 2016-03-05
  • 2020-05-13
  • 1970-01-01
  • 2020-01-23
  • 1970-01-01
  • 2015-02-03
  • 1970-01-01
相关资源
最近更新 更多