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;
}
Node23是一种嵌套类型,其封闭类型的模板参数无法那么容易推导。因此,您必须通过模板运算符()
显式指定它们。
改变这条线
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);
摆脱了“无法推导模板参数”的错误。它不漂亮,但现在可以编译了。
如果您这样更改函数调用运算符的声明:
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 意图 模板方法模式是一种行为设计模式, 它在超类中定义了一个算法的框架, 允许子类在不修改结构的情况下重写算法的特定步骤。 问题 假如你正在开发一款分析公司文档的数据挖掘程序。 用户需要向程序输入各种格式 (PDF、 DOC 或 CSV) 的文档, 程序则会试图从这些文件中抽取有意义的数据, 并以统一的格式将其返回给用户。 该程序的首个版本仅支持 DOC 文
一、定义 模板方法是基于继承的设计模式,可以很好的提高系统的扩展性。 java中的抽象父类、子类 模板方法有两部分结构组成,第一部分是抽象父类,第二部分是具体的实现子类。 二、示例 Coffee or Tea (1) 把水煮沸 (2) 用沸水浸泡茶叶 (3) 把茶水倒进杯子 (4) 加柠檬 /* 抽象父类:饮料 */ var Beverage = function(){}; // (1) 把水煮沸
问题 定义一个算法的结构,作为一系列的高层次的步骤,使每一个步骤的行为可以指定,使属于一个族的算法都具有相同的结构但是有不同的行为。 解决方案 使用模板方法( Template Method )在父类中描述算法的结构,再授权一个或多个具体子类来具体地进行实现。 例如,想象你希望模拟各种类型的文件的生成,并且每个文件要包含一个标题和正文。 class Document produceDocu
使用以下代码生成时 生成以下诊断(代码后): 诊断: 有趣的部分不是关于歧义错误本身(这不是这里主要关注的问题)。有趣的是,当仅使用函数名调用fun时,第一个fun的模板参数F被解析为纯函数类型double(double),而第二个fun的模板参数F被解析为更期望的函数指针类型。 然而,当我们将调用<代码>乐趣(测试) 更改为<代码>乐趣( 这种行为似乎是所有Clang和GCC(以及Visual