这里我有一系列重载函数,它们都是vector或initializer_list的输入。我想在客户端代码输入空的initializer_list时处理特殊情况。问题是编译器无法确定这种空列表中的数据。所以我的问题是如何在函数声明中解决这种情况。
#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
}
错误消息:
<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) {}
- 没有效果。我不知道如何正确宣布它。
答案 0 :(得分:3)
我希望有更好的答案,但是您可以利用以下事实:使用已定义类型的空括号进行列表初始化更喜欢initializer_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) {}
如果您没有使用string
,则可以使用template<typename T> void func(initializer_list<T>)
模板,empty
重载,因为非模板重载比模板重载更受欢迎,但遗憾的是case字符串文字调用推断为initializer_list<const char *>
,很难转换为initializer_list<string>
。
答案 1 :(得分:3)
单独使用参数无法区分它。您可以将其中一个作为模板,然后这将更加昂贵,并且不太适合重载解析
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) {}
现在调用func({})
将优先于函数模板的最后一个函数。请注意,func({"hello", "world"})
仍然优先于非模板向量捕获函数的函数模板,因为参数转换成本比是否从模板合成候选更重要。