当前位置: 首页 > 知识库问答 >
问题:

函子的模板方法“无法推导模板参数”

岳俊晖
2023-03-14

std=C14的g在函子类的模板方法(本身不是模板)上给我一个“无法推断模板参数'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;
}

共有3个答案

梁丘高朗
2023-03-14

Node23是一种嵌套类型,其封闭类型的模板参数无法那么容易推导。因此,您必须通过模板运算符()显式指定它们。

卢树
2023-03-14

改变这条线

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

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

裴翰学
2023-03-14

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

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

编译器无法推断类型<code>键

 类似资料:
  • 另一个有用的可能示例:(伪代码)

  • 如果我没有理解错的话,类模板定义了一个函数,所以当我调用时,编译器有可能进行隐式强制转换,但是在函数模板的情况下,此时没有函数定义,所以隐式强制转换不会发生。 但我不明白为什么编译器不能创建函数定义,然后应用隐式强制转换? 错误是: 在函数“int main()”中:    25:24:错误:调用“test2::add(void(&)(int))”没有匹配函数    25:24:注:候选人是:  

  • 问题 定义一个算法的结构,作为一系列的高层次的步骤,使每一个步骤的行为可以指定,使属于一个族的算法都具有相同的结构但是有不同的行为。 解决方案 使用模板方法( Template Method )在父类中描述算法的结构,再授权一个或多个具体子类来具体地进行实现。 例如,想象你希望模拟各种类型的文件的生成,并且每个文件要包含一个标题和正文。 class Document produceDocu

  • 亦称: Template Method 意图 模板方法模式是一种行为设计模式, 它在超类中定义了一个算法的框架, 允许子类在不修改结构的情况下重写算法的特定步骤。 问题 假如你正在开发一款分析公司文档的数据挖掘程序。 用户需要向程序输入各种格式 (PDF、 DOC 或 CSV) 的文档, 程序则会试图从这些文件中抽取有意义的数据, 并以统一的格式将其返回给用户。 该程序的首个版本仅支持 DOC 文

  • 一、定义 模板方法是基于继承的设计模式,可以很好的提高系统的扩展性。 java中的抽象父类、子类 模板方法有两部分结构组成,第一部分是抽象父类,第二部分是具体的实现子类。 二、示例 Coffee or Tea (1) 把水煮沸 (2) 用沸水浸泡茶叶 (3) 把茶水倒进杯子 (4) 加柠檬 /* 抽象父类:饮料 */ var Beverage = function(){}; // (1) 把水煮沸

  • 使用以下代码生成时 生成以下诊断(代码后): 诊断: 有趣的部分不是关于歧义错误本身(这不是这里主要关注的问题)。有趣的是,当仅使用函数名调用fun时,第一个fun的模板参数F被解析为纯函数类型double(double),而第二个fun的模板参数F被解析为更期望的函数指针类型。 然而,当我们将调用<代码>乐趣(测试) 更改为<代码>乐趣( 这种行为似乎是所有Clang和GCC(以及Visual