C++ 如何重载空的std::initializer\u列表?

C++ 如何重载空的std::initializer\u列表?,c++,c++11,overloading,initializer-list,C++,C++11,Overloading,Initializer List,这里我有一系列重载函数,它们的输入要么是向量,要么是初始值设定项列表。我想处理客户机代码输入空初始值设定项列表时的特殊情况。问题是编译器无法确定在这样的空列表中应该包含哪些数据。所以我的问题是,在这种情况下,我如何处理函数声明 #include <string> #include <vector> using namespace std; void func(vector<string> v) { } void func(vector<wstring&

这里我有一系列重载函数,它们的输入要么是向量,要么是初始值设定项列表。我想处理客户机代码输入空初始值设定项列表时的特殊情况。问题是编译器无法确定在这样的空列表中应该包含哪些数据。所以我的问题是,在这种情况下,我如何处理函数声明

#include <string>
#include <vector>

using namespace std;
void func(vector<string> v) { }
void func(vector<wstring> v) { }
void func(initializer_list<string> iv) {}
void func(initializer_list<wstring> iv) {}

int main() {
  using namespace std;
  func({"apple", "banana"});
  func({L"蘋果", L"香蕉"});
  func({}); // special case
}
#包括
#包括
使用名称空间std;
void func(向量v){}
void func(向量v){}
void func(初始值设定项_list iv){}
void func(初始值设定项_list iv){}
int main(){
使用名称空间std;
func({“苹果”、“香蕉”});
func({L“蘋果", L“香蕉"});
func({});//特例
}
错误消息:

<stdin>: In function 'int main()':
<stdin>:14:10: error: call of overloaded 'func(<brace-enclosed initializer list>)' is ambiguous
<stdin>:14:10: note: candidates are:
<stdin>:5:6: note: void func(std::vector<std::basic_string<char> >)
<stdin>:6:6: note: void func(std::vector<std::basic_string<wchar_t> >)
<stdin>:7:6: note: void func(std::initializer_list<std::basic_string<char> >)
<stdin>:8:6: note: void func(std::initializer_list<std::basic_string<wchar_t> >)
:在函数“int main()”中:
:14:10:错误:重载“func()”的调用不明确
:14:10:注:候选人包括:
:5:6:注:void func(标准::向量)
:6:6:注:void func(标准::向量)
:7:6:注意:void func(std::initializer\u列表)
:8:6:注意:void func(std::initializer\u列表)

void func(初始值设定项_list iv){}
-无效。我不知道如何正确声明它。

我希望有一个更好的答案,但您可以利用这样一个事实,即使用定义类型的空括号进行列表初始化时,默认构造函数优先于
初始值设定项\u list
构造函数。不幸的是,这意味着必须关闭
func到单个参数类型的重载构造函数集中:

using namespace std;
struct parameter {
   // representation left as an exercise - perhaps Boost.Variant?
   parameter(vector<string> v) {}
   parameter(vector<wstring> v) {}
   parameter(initializer_list<string> iv) {}
   parameter(initializer_list<wstring> iv) {}
   parameter() {}  // default constructor - func({}) calls this
};
void func(parameter) {}
使用名称空间std;
结构参数{
//作为一个练习,可能是增强。变体?
参数(向量v){}
参数(向量v){}
参数(初始值设定项_list iv){}
参数(初始值设定项_list iv){}
parameter(){}//默认构造函数-func({})调用
};
void func(参数){}

如果未使用
字符串
,则可以使用模板,即
模板void func(初始值设定项列表)
使用
空的
重载,因为非模板重载比模板重载更可取,但不幸的是,在您的情况下,字符串文字调用被推断为
初始值设定项列表
,这很难转换为
初始值设定项列表

单独使用参数无法区分这一点。您可以不过,将其中一个作为模板,这样成本会更高,对于重载解析来说也不太可取

void func(vector<string> v) { }
void func(vector<wstring> v) { }
template<typename = void>
void func(initializer_list<string> iv) {}
void func(initializer_list<wstring> iv) {}
void func(向量v){
void func(向量v){}
模板
void func(初始值设定项_list iv){}
void func(初始值设定项_list iv){}

现在调用
func({})
将更喜欢最后一个函数而不是函数模板
仍然更喜欢函数模板而不是非模板向量获取函数,因为参数转换成本比是否从模板合成候选向量更重要。

根据我到目前为止的测试,当存在冲突
向量
初始值设定项列表
时,列表将获胜。什么过载您是否希望在只有
vector
vector
可用的场景中被选中,因为这似乎是一个问题。我喜欢这个想法。也许在构造函数中,您可以转发到一个原始重载。每个重载只需执行
funcReal(v);
funcReal(iv)
,默认构造函数将构造函数委托给其中一个构造函数。