将向量或向量的向量或...的向量(你懂的)传递给函数

Xon*_*nxt 4 c++ vector

我正在为机器学习编写 API,我需要一个重载函数,该函数可以接收向量作为参数,也可以接收向量向量(用于批处理作业)。

不过,我在调用该函数时遇到了一些问题。

作为一个更简单的示例,该函数可能如下所示:

void bar( const std::vector<float>& arg ) {
  std::cout << "BAR: Vector of float" << std::endl;
}
void bar( const std::vector<std::vector<float>>& arg ) {
  std::cout << "BAR: Vector of vectors of float" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

所以,我希望我可以这样称呼它:

 bar( { 1,2,3 } );
 bar( { { 1,2,3 } } );
Run Code Online (Sandbox Code Playgroud)

但是在第二个 IDE 中,IDE 抱怨说,两个重载函数都匹配参数列表,因此我必须像这样调用它才能使其工作。

bar( { { { 1,2,3 } } } );
Run Code Online (Sandbox Code Playgroud)

这是为什么?那不是向量的向量(即“3D-向量”)吗?

当我传递一个先前初始化的向量时也是如此:

std::vector<float> v = { 1,2,3,4,5 };

bar( v );
bar( { v } );
Run Code Online (Sandbox Code Playgroud)

两者都打印出BAR: Vector of float消息。所以我现在必须去:

bar( { { { v } } } );
Run Code Online (Sandbox Code Playgroud)

让它工作,这现在看起来像一个 4D 向量。我错过了什么吗?

Nat*_*ica 6

欢迎来到地狱。当你有

bar( { 1,2,3 } );
Run Code Online (Sandbox Code Playgroud)

{ 1,2,3 }被视为一个std::initializer_list<float>和唯一可行的函数调用void bar( const std::vector<float>& arg )

当你有

bar( { { 1,2,3 } } );
Run Code Online (Sandbox Code Playgroud)

现在{ { 1,2,3 } }可以被解释为表示 a 的外部大括号std::vector<float>,内部大括号表示std::initializer_list<float>它,或者可以std::initializer_list<std::initializer_list<float>>是用于构造 2d 向量的 a 的构造。任何一个选项都一样好,所以你会产生歧义。正如你所发现的,解决方案是

bar( { { { 1,2,3 } } } );
Run Code Online (Sandbox Code Playgroud)

所以现在最外面的一组大括号表示创建 a std::vector<std::vector<float>>,第二个最外面的大括号表示 a 的开始,最std::initializer_list<std::initializer_list<float>>里面的大括号是 a 的一个元素。

bar( v );
bar( { v } );
Run Code Online (Sandbox Code Playgroud)

它有点复杂。显然bar( v );会做你想做的事,但bar( { v } );实际上与[over.ics.list]bar( { { 1,2,3 } } );中的规则不同。具体来说,第 7 段说这是通过复制构造函数创建 a的精确匹配,而创建 a是用户定义的转换。这意味着跟注是更好的匹配,这就是您所看到的。你需要使用{ v }std::vector<float>std::vector<std::vector<float>>void bar( const std::vector<float>& arg )

bar( { { { v } } } );
Run Code Online (Sandbox Code Playgroud)

这样外面的一组大括号表示std::vector<std::vector<float>>,中间的一组是 的开始,std::initializer_list<std::vector<float>>最里面的一组是该std::vector<float>列表的单个元素。