2017-03-21 6 views
2

私はC++でCRTP(奇妙な再帰的テンプレートパターン)を学んでいます。CRTP(不思議な再帰的テンプレートパターン)が別のプライベートベースクラスの同じ名前の関数を選択しようとするのはなぜですか?

私はCRTPを学ぶために以下のコードを作った。

コードでは、基本クラスからCRTPの別の基本クラスを使用してイテレータを取得しようとしました。

gccコンパイラは、以下のtest_get_iterator_by_crtp()でGET_CONTAINRE_ITERATOR_CRTP :: begin()関数を選択できません。 GET_CONTAINRE_ITERATOR_CRTP <(int)> :: begin()の名前をbegin_another()に変更すると、gccがGET_CONTAINRE_ITERATOR_CRTP <(int)>およびContainerIterator <(int)>のbegin()を混乱させるようです。

私はci.template begin()を期待しました。以下はContainerIterator :: begin()にできません。これはプライベートベースクラスとして実装されており、直接アクセスできないためです。

begin()があいまいである理由を教えてください。 私が簡単な間違いや誤解をした場合、私を許してください。どうもありがとうございました。

template <typename T> 
class ContainerIterator : public std::vector<T> { 
public: 
    auto begin(void) { 
     return std::vector<T>::begin(); 
    } 
}; 

template <typename Derived> 
class GET_CONTAINRE_ITERATOR_CRTP { 
public: 

    template <typename T> 
    auto begin(void) { 
     Derived* host = static_cast<Derived*>(this); 
     // The following line makes a compile error of ambiguous name, begin(). 
     return host->template ContainerIterator<T>::begin(); 
    } 
}; 

// CI = Container Iterator 
class CI : private ContainerIterator<int>, public GET_CONTAINRE_ITERATOR_CRTP<CI> { 
public: 
    friend class GET_CONTAINRE_ITERATOR_CRTP<CI>; 
}; 

void test_get_iterator_by_crtp(void) { 
    CI ci{}; 
    auto it = ci.template begin<int>(); 
} 

エラーメッセージ:

error: request for member ‘begin’ is ambiguous 
+1

私のためにコンパイルします。 Apple clang 8.0.0(clang-800.0.42.1) –

+0

@Richard Hodges:報告していただきありがとうございます。私のコンパイラはgcc(Ubuntu 5.4.0-6ubuntu1〜16.04.4)5.4.0 20160609. – mora

答えて

1

あなたは明示的に基本テンプレートクラスはメソッドbegin()を実装するコンパイラを教えてください。あなたのCIクラス内には、パブリックセクションに1つのusing命令を追加することによってそれを行うことができます:デフォルトコンパイラによって

using GET_CONTAINRE_ITERATOR_CRTP<CI>::begin; 

GET_CONTAINRE_ITERATOR_CRTP temlateのいくつかの専門分野がbegin()方法なしに実現できることが公正な提案を行います。あなたはスコット・マイヤーズ( "効果的なC++")によって項目43を参照することができfuther情報について

UPD: using GET_CONTAINRE_ITERATOR_CRTP<CI>::begin;意志が役立ちます。しかし、そのような振る舞いの主な理由は、GCCが「名前検索」と「アクセスチェック」を行う順序です。標準に従って:The access rules (Clause 11) are considered only once name lookup and function overload resolution (if applicable) have succeeded.これは、あいまいな問題beginの名前につながります。 Clangは異なった振る舞いをしているが、それは明らかではない。

+0

ありがとうございます。私はここにEffective C++を持っていません。しかし、私は後でそれを読むでしょう。 ...ところで、gccのこのバグはありますか? Richard Hodgesは、clangがエラーであると判断しないと報告したためです。 – mora

+0

これはClangコンパイラの "機能"(エラー??)だと思います。あなたはここでいくつかの追加情報を読むことができます[C++ Faq Lite。](https://isocpp.org/wiki/faq/templates#nondependent-name-lookup-members) –

+0

ありがとうございます。私は本屋に行って、あなたが推薦したアイテム43とそのサイトを読んだ。私は彼らが依存する名前で基本クラスにアクセスする方法を指示すると思います。しかし、私の質問は、gccがプライベートに継承されている基本クラスの機能を調べようとする理由です。プライベートContainerIterator 。 – mora