【问题标题】:template method of functor "can't deduce template parameter"仿函数的模板方法“不能推导出模板参数”
【发布时间】:2016-07-23 11:14:16
【问题描述】:

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...
};

层序遍历调用函子的函数调用运算符,传递给它两个参数。

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(); 
   }
}

函子很简单:

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;
}

【问题讨论】:

标签: c++ templates methods parameters c++14


【解决方案1】:

如果您像这样更改函数调用运算符的声明:

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

编译器无法推断出KeyValue 类型,因为tree23&lt;Key, Value&gt;::Node23KeyValue非推断上下文 (§14.8.2.5) ,强制你使用显式函数模板调用语法。

【讨论】:

  • 谢谢。现在我很清楚,作为node 传递的类型是否恰好是某个树 类实例的嵌套类型并不重要,正如您所指出的那样,这导致了一个未扣除的上下文对于KeyValue
【解决方案2】:

改变这一行

f(*current, current_tree_level);

在方法中

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

成为

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

摆脱了“无法推断模板参数”错误。它不是很漂亮,但现在可以编译了。

【讨论】:

    【解决方案3】:

    Node23 是一个嵌套类型,它的封闭类型的模板参数不能那么容易推导出来。因此,您必须通过 template operator() 明确指定它们。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-12-05
      • 2021-07-12
      • 1970-01-01
      • 2011-08-28
      • 1970-01-01
      • 2012-02-21
      相关资源
      最近更新 更多