推断初始化列表大小的模板参数

8

我有以下(无法编译的)代码:

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

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

在这里,我想将任意数量的int传递给函数foo--为了方便起见,我将使用std :: initializer_list表示法。 我尝试使用std :: array来聚合int(如上面的代码所示),然而,由于int作为std :: initializer_list传递,编译器无法推导出数组大小。
使用std :: initializer_list而不是std :: array也无法解决问题,因为(与std :: array相比),std :: initializer_list的大小未被捕获为模板参数。
有人知道可以使用哪种数据结构,以便可以使用std :: initializer_list记号传递int,而不需要显式传递foo的模板参数N吗?
非常感谢。

请注意,自C++14以来,std::initializer_list::size是一个constexpr函数。那就可以了吧? - StoryTeller - Unslander Monica
@StoryTeller 不行,因为对象参数必须是“constexpr”,而函数参数不能是“constexpr”。 - Columbo
对你来说,调用 foo(1,2) (无论有多少个参数)是否可行? - krzaq
@Columbo,你确定吗?如果无法将参数传递给constexpr函数,则似乎不可行。 - StoryTeller - Unslander Monica
@StoryTeller 嗯...严格来说,如果函数体不相应地使用this,那么对象参数不需要是constexpr,但我们无法知道它是否这样做。回答你的问题:参数不能是constexpr,但我们可能会有其他情况。 - Columbo
2个回答

11

感谢 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 (&arr)[N]是什么吗:一个数组?此外,使用不带constint (&arr)[N]是无法工作的,你能帮我理解为什么吗? - abraham_hilbert
1
@abraham_hilbert 你觉得加上 void foo (int) {/*N=0的代码*/} 怎么样? - Columbo
有没有类似于模板类及其构造函数的等效物(例如,Klass k({1,2,3}) 将会特化模板 Klass<int N>)? - Osman-pasha
1
@Osman-pasha 你在寻找扣除指南吗?? - Columbo
@Columbo 是的,谢谢。我甚至不知道这些东西的存在。 - Osman-pasha
显示剩余3条评论

3
如果不必使用初始化列表,您可以使用可变模板参数包:
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的答案。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接