テンプレート引数として指定されたクラスに対してアクションを実行するテンプレート化されたクラスがあります。一部のクラスでは、機能を 1 つのクラスに「グループ化」して、呼び出し元を簡単にしたいと考えています。実際、コードは次のようになります (名前は変更されています)。
template<typename T>
class DoSomeProcessing
{
public:
process(T &t);
};
class ProcessingFrontEnd : public DoSomeProcessing<CustomerOrder>, public DoSomeProcessing<ProductionOrder>
{
};
問題は、引数として CustomerOrder を指定して ProcessingFrontEnd::process を呼び出すと、コンパイラがそれについて文句を言うことです。
小規模なテスト アプリケーションで問題を再現しようとしました。これはコードです:
#include <vector>
class X : public std::vector<char>
, public std::vector<void *>
{
};
int main(void)
{
X x;
x.push_back('c');
return 0;
}
実際、これをコンパイルすると、Microsoft の VS2010 コンパイラは次のエラーを返します。
test.cpp
test.cpp(11) : error C2385: ambiguous access of 'push_back'
could be the 'push_back' in base 'std::vector<char,std::allocator<char> >'
or could be the 'push_back' in base 'std::vector<void *,std::allocator<void *> >'
test.cpp(11) : error C3861: 'push_back': identifier not found
このテスト アプリケーションをさまざまな型 (char+void*、double+void*) と呼び出しのさまざまな引数 ('c'、3.14) でテストしましたが、エラー メッセージは常に同じです。
これを VS2005 と VS2010 でテストしましたが、常に同じエラーが発生します。
コンパイラが呼び出す正しい関数を判断できないのはなぜですか? これがコンパイラを混乱させるのはなぜですか? それとも、Microsoft コンパイラの単なるバグですか?
編集: クラスに 2 つの push_back メソッドを明示的に追加すると、次のようになります。
class X : public std::vector<char>
, public std::vector<void *>
{
public:
void push_back(char c) {}
void push_back(void *p) {}
};
コンパイラはもう文句を言いません。したがって、これらのメソッドを使用すると、文字と void-pointer を明確に区別できます。2 つの push_back メソッドが親から継承されている場合、なぜ彼はこれを行うことができないのでしょうか?