2016-04-04 11 views
1

g ++ std = C++ 14では、ファンクタクラスのテンプレートメソッドでテンプレートパラメータ 'Key'を推測できませんでしたテンプレート自体ではありません)。 私は理由を理解できません。コードはうまくいくように見えます。ファンクタのテンプレートメソッド "テンプレートパラメータを推論できません"

私は2 3ツリーを実装していますが、それはファンクタを取るレベルオーダートラバーサルメソッドを持っています。 オペレータ。 tree23コードは基本的にはこれです:

template<class Key, class Value> class tree23 { 
public: 
class Node23 { 
     friend class tree23<Key, Value>;    
    public: 
    // snip... 

     friend std::ostream& operator<<(std::ostream& ostr, const Node23& node23) 
     { 
     // snip... outputs the keys and values of node23 to ostr. 
     } 

    private: 

     Node23 *parent; 
     std::array<Key, 2> keys; 
     std::array<Value, 2> values; 
     std::array<std::unique_ptr<Node23>, 3> children; 

     int totalItems; // either TwoNodeItems or ThreeNodeItems 
     // snip... 
}; 

    template<typename Functor> void levelOrderTraverse(Functor f) const noexcept; 
    // snip... 
}; 

レベル順トラバーサルはそれを2つのパラメータを渡して、ファンクタの関数呼び出し演算子を呼び出します。

template<class Key, class Value> template<typename Functor> \ 
void tree23<Key, Value>::levelOrderTraverse(Functor f) const noexcept 
{ 
    std::queue< std::pair<const Node23*, int> > queue; 

    Node23 *proot = root.get(); 

    if (proot == nullptr) return; 

    auto initial_level = 1; // initial, top level is 1, the root. 

    queue.push(std::make_pair(proot, initial_level)); 

    while (!queue.empty()) { 

     std::pair<const Node23 *, int> pair_ = queue.front(); 

     const Node23 *current = pair_.first; 

     int current_tree_level = pair_.second; 

     // invokes functor's operator()(const Node23&, int)? 
     f(*current, current_tree_level); 

     if (!current->isLeaf()) { 

      for(auto i = 0; i < current->getChildCount(); ++i) { 

       queue.push(std::make_pair(current->children[i].get(), current_tree_level + 1)); 
      } 
     } 

     queue.pop(); 
    } 
} 

ファンクタは非常に簡単です:メソッド

template<class Key, class Value> template<typename Functor> \ 
void tree23<Key, Value>::levelOrderTraverse(Functor f) const noexcept 

class levelOrderPrinter { 

    private: 
    // snip...  
    public: 
     levelOrderPrinter(std::ostream& ostr_lhs, int depth); 
     levelOrderPrinter(levelOrderPrinter&); 
     levelOrderPrinter(const levelOrderPrinter&); 

     template<class Key, class Value> 
     void operator()(const typename tree23<Key, Value>::Node23& node, 
         int current_level) noexcept; 
}; 

template<class Key, class Value> 
void levelOrderPrinter::operator()(const typename tree23<Key, Value>::Node23& node, 
          int current_level) noexcept 
{ 
    // Did level change? 
    if (level != current_level) { 

     level = current_level; 
     ostr << "\n\n" << "level = " << level; 

     // Provide some basic spacing to tree appearance. 
     std::size_t num = tree_depth - level + 1; 

     std::string str(num, ' '); 

     ostr << str; 
    } 

    ostr << node; 
} 
+0

関連:http://stackoverflow.com/q/1268504/951890 –

答えて

1

この行を変更する

f(*current, current_tree_level); 

します
f.template operator()<Key, Value>(*current, current_tree_level); 

"テンプレートパラメータを推定できません"というエラーを取り除きました。それはかなりではありませんが、今コンパイルされます。

1

Node23はネストされたタイプであり、その囲みタイプのテンプレートパラメータを簡単に推測することはできません。したがって、明示的に指定する必要がありますtemplate operator()

2

あなたがそうのようなあなたの関数呼び出し演算子の宣言を変更した場合:

template<class Node> 
void levelOrderPrinter::operator()(const Node& node, int current_level) noexcept 

その後、コンパイラはNodeの種類を推定することができるようになります。元のコードで

template<class Key, class Value> 
void levelOrderPrinter::operator()(const typename tree23<Key, Value>::Node23& node, 
            int current_level) noexcept 

tree23<Key, Value>::Node23非演繹KeyValue(§14.8.2.5)のコンテキスト、強制的であるため、コンパイラは、タイプKeyまたはValueを推定することができません明示的な関数テンプレート呼び出し構文を使用します。

+0

ありがとう。 'node'として渡された型が何らかのツリーのネストされた型であるかどうかはまったく問題ではないことが今や分かりました。あなたが指摘したように、これは' Key'のための非控除コンテキストとValue。 –

関連する問題