GCCでは起こらないが、Visual C++では起こります。'typedef'に関わっているかもしれず、もしもそうなら、この方法で解決されます。
話題
About: C++
この記事の目次
- 開始コンテキスト
- ターゲットコンテキスト
- オリエンテーション
- 本体
- 1: ミステリアスな「unable to match function definition to an existing declaration」コンパイルエラーに遭遇する、Visual C++のみで
- 2: その理由は?
- 3: ある解決策
開始コンテキスト
- 読者は、C++の基本的知識を持っている、たとえ、その、広く誤って伝えられているいくつかの要素を正確に理解していないとしても。
ターゲットコンテキスト
- 読者は、'typedef'に関わる「unable to match function definition to an existing declaration」Visual C++エラーを解決する方法を知る。
オリエンテーション
ある、スタンダードmap互換要素群順序維持マップが、ある記事にて作成されました。
C++テンプレートの実態が、ある記事にて調査されました。
本体
1: ミステリアスな「unable to match function definition to an existing declaration」コンパイルエラーに遭遇する、Visual C++のみで
Hypothesizer 7
以下(ある、スタンダードmap互換要素群順序維持マップからの抜粋)は、GCCでは問題なくコンパイルされるが、Visual C++ではそうではない。
'theBiasPlanet/coreUtilities/collections/NavigableLinkedMap.hpp'
@C++ ソースコード
#ifndef __theBiasPlanet_coreUtilities_collections_NavigableLinkedMap_hpp__
#define __theBiasPlanet_coreUtilities_collections_NavigableLinkedMap_hpp__
using namespace ::std;
namespace theBiasPlanet {
namespace coreUtilities {
namespace collections {
template <typename T, typename U, typename W = less <T>> class NavigableLinkedMap {
public:
typedef T key_type;
typedef U mapped_type;
typedef W key_compare;
public:
typedef pair <key_type const, mapped_type> value_type;
class BaseIterator {
};
class NonConstantIterator : public BaseIterator {
public:
typedef pair <key_type const, mapped_type> value_type;
virtual value_type & operator * ();
};
class ConstantIterator : public BaseIterator {
public:
typedef pair <key_type const, mapped_type> const value_type;
virtual value_type & operator * ();
};
};
}
}
}
#endif
'theBiasPlanet/coreUtilities/collections/NavigableLinkedMap.cpp'
@C++ ソースコード
#include "theBiasPlanet/coreUtilities/collections/NavigableLinkedMap.hpp"
namespace theBiasPlanet {
namespace coreUtilities {
namespace collections {
template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::NonConstantIterator::value_type & NavigableLinkedMap <T, U, W>::NonConstantIterator::operator * () {
// Omitted
}
template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::ConstantIterator::value_type & NavigableLinkedMap <T, U, W>::ConstantIterator::operator * () {
// Omitted
}
}
}
}
エラーは、「template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::ConstantIterator::value_type & NavigableLinkedMap <T, U, W>::ConstantIterator::operator * ()」に言及し、それは、「unable to match function definition to an existing declaration」だと言っている . . .
注目すべきだが、ほとんど同じメソッドである「template <typename T, typename U, typename W> typename NavigableLinkedMap <T, U, W>::NonConstantIterator::value_type & NavigableLinkedMap <T, U, W>::NonConstantIterator::operator * ()」は問題なく受け入れられている。 . . . はあ?
2: その理由は?
Hypothesizer 7
エラー判定されたものの、受け入れられたものからの唯一の相違は、「ConstantIterator」という名前だけであるように見える、「NonConstantIterator」の代わりに。
えーと、その特定の名前は、一種のトラップなのだろうか?その名前を変えろということなのか?
そういうことでは、勿論、ない。
リーズナブルに考えると、原因は、「ConstantIterator::value_type」の内部にしかありえない。実際、他の何でありえるというのか?
結局判明したのだが、当該ヘッダファイル内の「typedef pair <key_type const, mapped_type> const value_type」中の最後の「const」が原因である。
しかしなぜだ?それの何が悪いというのか? . . . 正直に言って、私は知らない。
当該ヘッダファイル内で「const」が取り除かれ、'cpp'ファイル内でリターンタイプが「typename NavigableLinkedMap <T, U, W>::ConstantIterator::value_type const &」へ変更されたら、コードは問題なくコンパイルされる。ふーむ . . .
しかし、私はその'ConstantIterator::value_type'の宣言を変更できない、なぜなら、それは公開されたタイプだからだ!もしも、それが変更されたら、'::std::map'との互換性が壊れてしまうだろう。
結論として、私は、その理由を理解しないが、当該エラーを引き起こしている部分は知っている。
3: ある解決策
Hypothesizer 7
えーと、私の推論は、「ConstantIterator::value_type」の宣言を変えることはできない、したがって、それをソースファイル内で使わないようにするしかない、というものだ。
そこで、私は、'NonConstantvalue_type'というタイプを、'typedef pair <key_type const, mapped_type>'として追加し、'cpp'ファイル中のリターンタイプの表現を'typename NavigableLinkedMap <T, U, W>::ConstantIterator::NonConstantvalue_type const &'へ変更した(それは、そのリターンタイプを実際には変更しない)。 . . . それでうまくいくのか?はい。
正直に言って、そのような余分な、本来存在する理由のないタイプを持たなければならないのは嬉しくないが、それが、私が思いついた最良の解決策だ。