2

看看这段代码:

template <typename K,typename T>
Pointer<typename Collection<T>::Iterator> BinaryTree<K,T>::GetBeginning() const
{
    return new BinaryTreeIterator(this,BinaryTreeIterator::Position::atBeginning);
}

当我尝试使用 VSTS 2008 编译它时,我得到:

error C2244: 'BinaryTree<K,T>::GetBeginning' : unable to match function definition to an existing declaration
see declaration of 'BinaryTree<K,T>::GetBeginning'
2>        definition
2>        'Pointer<Collection<T>::Iterator> BinaryTree<K,T>::GetBeginning(void) const'
2>        existing declarations
2>        'Pointer<Collection<T>::Iterator> BinaryTree<K,T>::GetBeginning(void) const'

声明:

Pointer<Iterator> GetBeginning() const;

在课堂内。BinaryTree 间接继承自 Collection,BinaryTreeIterator 间接继承自 Iterator,两者都是各自容器的嵌套类。

您可以很容易地看到,即使在错误报告中,定义和声明也是相同的。这里真的有问题吗?

我发现微软发布了一个修复程序:“某些模板代码无法编译,安装 Visual Studio 2005 Service Pack 1 后出现错误 C2244”。但是我找不到对 VSTS 2008 的任何引用。

因此,首先我想检查是否有人一眼就能发现代码中的真正错误,如果是 VS 的错,有没有人知道上述修补程序是否是解决方案并且是否与 2008 年相关。

4

3 回答 3

2

对于那些感兴趣的人,我尝试编写一个最小的示例来重现该问题:

template <typename T>
struct Pointer {};

template <typename T>
struct Collection {
    struct Iterator {};
};

template <typename K,typename T>
struct BinaryTree : Collection<T>{
    Pointer<typename Collection<T>::Iterator> GetBeginning() const;

    struct BinaryTreeIterator : Collection<T>::Iterator {
        template <typename X>
        BinaryTreeIterator(BinaryTreeIterator*, X) {}
        struct Position {
            static int atBeginning() { return 0; }
        };
    };
};

template <typename K,typename T>
Pointer<typename Collection<T>::Iterator> BinaryTree<K,T>::GetBeginning() const
{
    return Pointer<typename Collection<T>::Iterator>();
}

int main(){
    BinaryTree<int, float> bt;
    bt.GetBeginning();
}

是的,我也得到了错误。在我们看到的代码中,我看不到任何明显的错误,但话又说回来,这个例子使用的嵌套类和继承比大多数理智的 C++ 程序员在一年中所做的要多,所以我不能肯定地说您的代码是否正确。

此外,我不得不猜测很多才能将其拼凑在一起。(atBeginning 应该是什么?实际的类接口是什么?)

但我怀疑如果你不从其他所有东西继承所有东西,它会更好(并且更具可读性和更容易调试)。

更新 我尝试使用 GCC 和 Comeau 的在线编译器编译上述内容,并且都接受了它。所以看起来它可能是一个编译器错误。

于 2009-09-28T00:47:25.500 回答
1

您可能考虑的明显解决方案是仅在类定义中定义函数,而不是稍后重新定义它。

此外,将迭代器类型放入 typedef 中,如下所示:

template <typename T>
struct Pointer {};

template <typename T>
struct Collection {
    struct Iterator {};
};

template <typename K,typename T>
struct BinaryTree : Collection<T>{
    typedef typename Collection<T>::Iterator Iter;
    Pointer<Iter> GetBeginning() const;

    struct BinaryTreeIterator : Collection<T>::Iterator {
    };
};

template <typename K,typename T>
Pointer<typename BinaryTree<K,T>::Iter> BinaryTree<K,T>::GetBeginning() const
{
    return new BinaryTreeIterator(this,BinaryTreeIterator::Position::atBeginning);
}

int main(){
    BinaryTree<int, float> bt;
    bt.GetBeginning();
}

似乎修复它。不知道为什么,可能是一个错误...

于 2009-09-28T01:01:54.507 回答
0

如果您将其更改为以下内容,它将编译:

template <typename K,typename T>
struct BinaryTree : Collection<T> {
    Pointer<typename BinaryTree<K,T>::Iterator> GetBeginning() const;

};

template <typename K,typename T>
Pointer<typename BinaryTree<K,T>::Iterator> BinaryTree<K,T>::GetBeginning() const
{
    return Pointer<BinaryTree<K,T>::Iterator>();
}

一般来说,原始代码不太正确,因为它暗示 GetBeginning() 可以返回任何集合,而(我假设)它只能返回二叉树集合。

编辑:

经过一番挖掘,似乎 VC++ 不能很好地处理注入的类名。也就是说,如果您在方法声明中从 Collection::Iterator 中删除,原始代码将编译:

template <typename K, typename T>
struct BinaryTree : Collection<T> {
    Pointer<typename Collection::Iterator> GetBeginning() const;

};

template <typename K, typename T>
Pointer<typename Collection<T>::Iterator> BinaryTree<K,T>::GetBeginning() const
{
    return Pointer<Collection<T>::Iterator>();
}
于 2009-09-28T15:20:28.783 回答