How to overload an empty std :: initializer_list?

Here I have a series of overloaded functions that have both vector and initializer_list input. And I want to handle a special case where the client code enters an empty initializer_list file. The problem is that the compiler cannot figure out what data was allowed in such an empty list. So my question is, how do I address such a case in the function declaration.

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

- It does not work. I don't know how to properly declare it.

+3


source to share


2 answers


It is impossible to distinguish this from the parameter alone. You can make one of these a pattern, although this will be more expensive 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) {}

      



The call func({})

will now be preferred over the last function over the function template. Note that func({"hello", "world"})

still prefers the function template over the vector non-therapy function, because the cost of parameter transformation is more important than whether or not the candidate has been synthesized from the template.

+3


source


I hope for a better answer, but you can take advantage of the fact that initializing a list with empty curly braces of a certain type prefers the default constructor over the constructor initializer_list

. Unfortunately, this means having to overload the overload func

in a set of overloading constructors of the same type of parameters:

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 didn't string

, you could use a template, i.e. template<typename T> void func(initializer_list<T>)

, with overloading empty

, since non-template overloads are preferred over template overloads, but unfortunately in your case calls to string literals like initializer_list<const char *>

, which is difficult to convert to initializer_list<string>

.

+3


source







All Articles