简体   繁体   English

如何重载空std :: initializer_list?

[英]how to overload empty std::initializer_list?

Here I have series of overloaded functions that have as input either vector or initializer_list. 这里我有一系列重载函数,它们都是vector或initializer_list的输入。 And I want to handle the special case when client code inputs empty initializer_list. 我想在客户端代码输入空的initializer_list时处理特殊情况。 The problem is that compiler cannot determine what data was supposed in such empty list. 问题是编译器无法确定这种空列表中的数据。 So my question is how I address in function declaration such case. 所以我的问题是我如何在函数声明中解决这种情况。

#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
}

error message: 错误信息:

<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> >)

void func(initializer_list<void> iv) {} - has no effect. void func(initializer_list<void> iv) {} - 无效。 I don't know how to properly declare it. 我不知道如何正确宣布它。

I'm hoping there's a better answer, but you can exploit the fact that list-initialization with empty braces of a defined type prefers a default constructor to an initializer_list constructor. 我希望有一个更好的答案,但你可以利用这样一个事实,即使用已定义类型的空括号的列表初始化更喜欢initializer_list构造函数的initializer_list构造函数。 Unfortunately, this means having to turn the overload of func into an overload set of constructors of a single parameter type: 不幸的是,这意味着必须将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) {}

If you weren't using string , you could use a template ie template<typename T> void func(initializer_list<T>) with an empty overload, as non-template overloads are preferred to template overloads, but unfortunately in your case the string literal calls are inferred as initializer_list<const char *> , which is difficult to convert to initializer_list<string> . 如果您没有使用string ,则可以使用模板,即template<typename T> void func(initializer_list<T>)其中包含empty重载,因为非模板重载优先于模板重载,但不幸的是在您的情况下是字符串文字调用被推断为initializer_list<const char *> ,很难转换为initializer_list<string>

There's no way to distinguish this with the parameter alone. 没有办法单独用参数来区分它。 You can make one of them a template though, which will then be more costly and less preferable for overload resolution 您可以将其中一个作为模板,然后这将成本更高,并且不太适合重载解析

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) {}

Now calling func({}) will prefer the last function over the function template. 现在调用func({})将优先于函数模板的最后一个函数。 Note that func({"hello", "world"}) still prefers the function template over the non-template vector-taking function, because the parameter conversion cost is more important than whether or not a candidate was synthesized from a template. 请注意, func({"hello", "world"})仍然比非模板向量捕获函数更喜欢函数模板,因为参数转换成本比是否从模板合成候选更重要。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM