5

ここでは、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) {}- 効果はありません。適切に宣言する方法がわかりません。

4

2 に答える 2

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のオーバーロードがテンプレートのオーバーロードよりも優先されるため、オーバーロードを使用できますが、残念ながら、文字列リテラルの呼び出しは として推測されinitializer_list<const char *>、変換が困難initializer_list<string>です。

于 2013-01-30T18:31:03.583 に答える
3

パラメータだけでこれを区別する方法はありません。ただし、そのうちの 1 つをテンプレートにすることはできますが、これはよりコストがかかり、オーバーロードの解決にはあまり適していません。

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"})パラメータ変換コストは、候補がテンプレートから合成されたかどうかよりも重要であるため、非テンプレート ベクトル取得関数よりも関数テンプレートを優先することに注意してください。

于 2013-01-30T22:37:02.290 に答える