【问题标题】:Deduce template argument for size of initializer list推导出初始值设定项列表大小的模板参数
【发布时间】:2017-03-07 14:03:15
【问题描述】:

我有以下(不可编译的)代码:

template< size_t N >
void foo( std::array<int, N> )
{
  // Code, where "N" is used.
}

int main()
{
  foo( { 1,2 } );
}

在这里,我想将任意数量的ints 传递给函数foo——为方便起见,我将使用std::initializer_list 表示法。 我尝试使用std::array 来聚合ints(如上面的代码所示),但是,由于ints 作为std::initializer_list 传递,编译器无法推断出数组大小。

使用std::initializer_list 代替std::array 也不能解决问题,因为(与std::array 相比)std::initializer_list 的大小不会被捕获为模板参数。

有谁知道可以使用哪种数据结构,以便可以通过使用std::initializer_list 表示法而不显式传递foo 的模板参数N 来传递ints?

在此先感谢

【问题讨论】:

  • 请注意,std::initializer_list::size 是自 c++14 以来的 constexpr 函数。这样不行吗?
  • @StoryTeller 不行,因为对象参数必须是constexpr,而函数参数不能是constexpr
  • 调用foo(1,2)(对于任意数量的参数)对您有用吗?
  • @Columbo,你确定吗? constexpr 函数如果参数不能是 consexpr 似乎不可行。
  • @StoryTeller 好吧...严格来说,如果正文没有相应地使用this,则对象参数不必是constexpr,但我们不知道它是否使用。回答您的问题:参数不能是constexpr,但我们可以有其他场景。

标签: c++ c++14 initializer-list template-argument-deduction


【解决方案1】:

感谢core issue 1591,您可以使用

template <std::size_t N>
void foo( int const (&arr)[N] )
{
  // Code, where "N" is used.
}

foo({1, 2, 3});

【讨论】:

  • 非常感谢 - 解决方案有效!你能帮我理解int const (&amp;arr)[N]是什么:一个数组吗?此外,使用int (&amp;arr)[N] 而不使用const 是行不通的——你能帮我理解为什么吗?
  • @abraham_hilbert 1) int const (&amp;arr)[N] 是对数组的 const 引用。 2)您是否知道临时对象可以绑定到 const 引用,但不能绑定到非 const 引用?好吧,我们正在创建一个临时数组并将其绑定到引用,这对于非常量引用是不允许的。
  • 我明白了,谢谢。一个问题仍然存在:空初始化列表的情况也应该是可能的(即N==0),这当前会导致编译器错误。你有什么解决办法吗?
  • @abraham_hilbert 添加void foo (int) {/*code for N=0*/}怎么样?
【解决方案2】:

如果不是必须使用初始化列表,您可以使用可变参数模板参数包:

template<size_t S>
void foo_impl(array<int, S> const&)
{
    cout << __PRETTY_FUNCTION__ << endl;
}

template<typename... Vals>
auto foo(Vals&&... vals) {
    foo_impl<sizeof...(vals)>({ std::forward<Vals>(vals)... });
}

你可以这样称呼它:

foo(1,2,3,4,5);

这会将常见的类型检查推迟到 std::array 的初始化点(除非您添加一些公认的丑陋断言),因此您可能应该更喜欢 Columbo 的答案。

【讨论】:

    猜你喜欢
    • 2022-11-20
    • 1970-01-01
    • 2021-12-25
    • 1970-01-01
    • 1970-01-01
    • 2021-11-24
    • 2019-02-17
    • 2013-07-09
    相关资源
    最近更新 更多