【发布时间】:2014-05-16 02:57:58
【问题描述】:
上下文
数据结构和算法课程的评估部分,练习使用 AVL 树和哈希表解析输入以创建字典文件,然后使用该文件执行粗略的拼写检查。
注意: 我不寻求帮助来解决这个不是我遇到困难的问题。我正在寻求帮助来理解 C++ 函数对象传递/使用的一个方面,这让我非常沮丧。 C++ 的这方面不属于评估的一部分,没有附加任何标记,我只是在提交代码时遇到了个人问题,我不喜欢它的设计。
问题
将仿函数传递给递归函数会导致编译器错误,“尝试使用已删除的函数”。我认为这是按值传递函子的问题,所以我将参数更改为按引用传递,这会产生“没有匹配的成员函数调用 ”,在这种情况下,我不知道如何更改函数声明以使其匹配。我也尝试过设置参数:const UnaryFunction& action(一个常量函数对象引用),但这会产生编译器错误“no matching function for call to object of type 'const std::__1::__mem_fn<void (DictGen::*)(std::__1::basic_string<char> &)>'”,在这种情况下我不明白为什么它不匹配DictGen::output 签名。
代码
AVL树类的相关部分:
template <class T>
struct AVLNode
{ // simple data carrier node for AVL tree
AVLNode<T>* lChild;
AVLNode<T>* rChild;
AVLBalance balFac;
T data;
};
template <class T>
class AVLTree<T>
{
...
AVLNode<T>* root;
template <class UnaryFunction>
void inorderAction( AVLNode<T>* node, UnaryFunction action )
{
if ( node != NULL )
{
inorderAction( node->lChild, action );
action( node->data ); // << problem line
inorderAction( node->rChild, action );
}
}
public:
template <class UnaryFunction>
void inorder( UnaryFunction action )
{
inorderAction( root, action );
}
}
DictGen 类的相关部分:
class DictGen
{
...
FILE* outStream;
AVLTree<std::string> dict;
void output( std::string& word )
{
fprintf( outstream, "%s\n", word.c_str() );
}
public:
goGoGadgetDictionaryGenerator()
{
...
dict.inorder( std::mem_fn( &DictGen::output ) ); // << also problem line
}
}
口译/笔译
AVL 树类有一个灵活的中序遍历,允许我使用给定的UnaryFunction action 来操作节点。 DictGen 对象使用 FILE* 进行初始化,因此 DictGen 实例可以输出到不同的文件,因此需要在 dict.inorder( ... ) 调用中传递成员函数对象。
迄今为止的努力/研究
我最初的解决方案是遵循我们教科书中给出的函数作为参数示例,其中涉及使用 C 函数指针和污染全局空间。虽然这行得通,但我对这个设计并不满意;我希望将此行为捆绑在一个 DictGen 类中。
在咨询了我的讲师和实验室导师之后,他们建议使用 C++ 仿函数,但由于有一段时间没有使用仿函数,因此无法帮助实现。
我奋力寻找关于 SO 的非常方便的材料(帮助我参考成员函数)、通过 Google 提供的几个仿函数教程以及来自斯坦福课程的关于仿函数实现和使用的优秀 PDF。然而,尽管所有这些资源都让我走到了这一步,但没有人能够阐明我目前的困境。我真的希望将参数设置为 const UnaryFunction& 可以解决它,但不明白为什么签名不匹配。
我也尝试过使用内联 lambda,但需要对象上下文才能访问 outStream。
在过去的四天里,我一直在努力解决这个问题,我唯一剩下的线索是一个 SO 帖子,随便说 C++ 规范包含有关函数对象的隐式删除的信息,但我无法取得任何进一步的进展。如果有解决我的问题的 SO 帖子,我找不到它。
问题
递归真的和这个问题有关系吗?
函子传递/使用是否有一些我没有掌握的新手方面?
是什么导致函数被删除?
当函数删除似乎不是问题时,我缺少什么让函数签名匹配?
这是我的第一篇 SO 帖子,我已尽力将提问的建议牢记在心。我欢迎任何建设性的批评来帮助我改进这篇文章,以便它既可以解决我的问题,又可以作为类似问题的未来资源。
【问题讨论】:
-
这是一个例外第一个问题!欢迎使用 Stack Overflow!
-
我们还需要查看 AVLNode,因为您将
node->data传递给action(),但不清楚node->data是什么 -
std::mem_fn( &DictGen::output )是一个二进制函子,它需要一个指向DictGen的引用或指针,然后是对std::string的引用。 -
@KennyEvitt 谢谢你,我付出了相当大的努力,希望能保持我所依赖的 SO 内容的质量。