嵌套在模板类中的模板类在 MSVC++ 中给出错误
我在 MSVC++ 2008 Express 版本中遇到无法理解的错误。首先,我将显示代码的精简版本(必要的包括忽略):
template <class Key,class Value>
class BinaryTree
{
public:
typedef std::pair<Key&,Value&> Element;
...
protected:
template <bool _Reverse>
class Iterator : public std::iterator<std::bidirectional_iterator_tag,Element>
{
public:
Iterator(const Iterator<_Reverse>& other);
Iterator& operator++();
...
protected:
typedef BinaryTree<Key,Value> Parent;
Iterator(Parent* parent,bool isEnd = false);
}
}
...
//Definition bodies (in the same file)
...
template <class Key,class Value,bool _Reverse> //line 118
inline BinaryTree<Key,Value>::Iterator<_Reverse>::Iterator(Parent* parent,bool isEnd = false)
//has an initialisation list (removing it didn't make a difference to the errors)
{
...
} //line 126
...
template <class Key,class Value,bool _Reverse>
inline BinaryTree<Key,Value>::Iterator<_Reverse>::Iterator(const Iterator<_Reverse>& other)
: _stack(other._stack), _parent(other._parent), _null(other._null)
{
} //line 132
...
//the next two are specialisations
template <class Key,class Value>
typename BinaryTree<Key,Value>::Iterator<false>& BinaryTree<Key,Value>::Iterator<false>::operator++()
{
...
} //line 196
template <class Key,class Value>
typename BinaryTree<Key,Value>::Iterator<true>& BinaryTree<Key,Value>::Iterator<false>::operator++()
{
...
} //line 211
我得到的错误是:
//normal constructor
binarytree.h(126) : error C3860: template argument list following class template name must list parameters in the order used in template parameter list
binarytree.h(126) : error C3855: 'BinaryTree<Key,Value>::Iterator<_Reverse>': template parameter '_Reverse' is incompatible with the declaration
binarytree.h(126) : error C2977: 'BinaryTree<Key,Value>::Iterator<_Reverse>' : too many template arguments
binarytree.h(118) : error C2952: 'BinaryTree<Key,Value>::Iterator<_Reverse>::Iterator' : template declaration missing template parameter list
//copy constructor
binarytree.h(132) : error C2244: 'BinaryTree<Key,Value>::Iterator<_Reverse>::{ctor}' : unable to match function definition to an existing declaration
definition
'BinaryTree<Key,Value>::Iterator<_Reverse>::Iterator(const BinaryTree<Key,Value>::Iterator<_Reverse> &)'
existing declarations
'BinaryTree<Key,Value>::Iterator<_Reverse>::Iterator(BinaryTree<Key,Value> *,bool)'
'BinaryTree<Key,Value>::Iterator<_Reverse>::Iterator(const BinaryTree<Key,Value>::Iterator<_Reverse> &)' //isn't this one clearly identical?
//operator++ - template specialisations
binarytree.h(196) : error C2244: 'BinaryTree<Key,Value>::Iterator<_Reverse>::operator ++' : unable to match function definition to an existing declaration
definition
'BinaryTree<Key,Value>::?$Iterator@$0A@ &BinaryTree<Key,Value>::Iterator<false>::operator ++(void)'
existing declarations
'BinaryTree<Key,Value>::Iterator<_Reverse> BinaryTree<Key,Value>::Iterator<_Reverse>::operator ++(int)'
'BinaryTree<Key,Value>::Iterator<_Reverse> &BinaryTree<Key,Value>::Iterator<_Reverse>::operator ++(void)'
binarytree.h(211) : error C2244: 'BinaryTree<Key,Value>::Iterator<_Reverse>::operator ++' : unable to match function definition to an existing declaration
definition
'BinaryTree<Key,Value>::?$Iterator@$00 &BinaryTree<Key,Value>::Iterator<true>::operator ++(void)'
existing declarations
'BinaryTree<Key,Value>::Iterator<_Reverse> BinaryTree<Key,Value>::Iterator<_Reverse>::operator ++(int)'
'BinaryTree<Key,Value>::Iterator<_Reverse> &BinaryTree<Key,Value>::Iterator<_Reverse>::operator ++(void)'
据我所知,每个成员函数都有这三个错误组之一。
我可以通过删除 Iterator 的模板化参数来解决所有这些问题,创建一个派生并重写必要函数的第二类 ReverseIterator。但我更愿意以这种方式修复它,以帮助我了解出了什么问题。
编辑:有人可以修复代码标签吗?似乎没有像我预期的那样工作。
编辑2:好的,第二个模板指令工作完美。然而,模板专业化错误似乎正在发生,因为如果您不专业化外部类,则不允许您专业化内部类。我可以解决这个问题,但这意味着我依赖编译器优化某些东西。例如,不要写:
template <class Key,class Value>
inline bool BinaryTree<Key,Value>::Iterator<false>::DoStuff()
{
return FalseCode();
}
template <class Key,class Value>
inline bool BinaryTree<Key,Value>::Iterator<true>::DoStuff()
{
return TrueCode();
}
I'veused:
template <class Key,class Value>
template <bool Reverse>
inline bool BinaryTree<Key,Value>::Iterator<Reverse>::DoStuff()
{
if(Reverse) //hopefully is optimised out; at compile time is either true or false
{
return TrueCode();
}
return FalseCode();
}
我忍不住认为更复杂的情况可能会导致编译器不会省略不必要的分支。我想这取决于编译器。
I'm getting errors I can't understand in MSVC++ 2008 express edition. First, I'll show a stripped version of my code (necessary includes ignored):
template <class Key,class Value>
class BinaryTree
{
public:
typedef std::pair<Key&,Value&> Element;
...
protected:
template <bool _Reverse>
class Iterator : public std::iterator<std::bidirectional_iterator_tag,Element>
{
public:
Iterator(const Iterator<_Reverse>& other);
Iterator& operator++();
...
protected:
typedef BinaryTree<Key,Value> Parent;
Iterator(Parent* parent,bool isEnd = false);
}
}
...
//Definition bodies (in the same file)
...
template <class Key,class Value,bool _Reverse> //line 118
inline BinaryTree<Key,Value>::Iterator<_Reverse>::Iterator(Parent* parent,bool isEnd = false)
//has an initialisation list (removing it didn't make a difference to the errors)
{
...
} //line 126
...
template <class Key,class Value,bool _Reverse>
inline BinaryTree<Key,Value>::Iterator<_Reverse>::Iterator(const Iterator<_Reverse>& other)
: _stack(other._stack), _parent(other._parent), _null(other._null)
{
} //line 132
...
//the next two are specialisations
template <class Key,class Value>
typename BinaryTree<Key,Value>::Iterator<false>& BinaryTree<Key,Value>::Iterator<false>::operator++()
{
...
} //line 196
template <class Key,class Value>
typename BinaryTree<Key,Value>::Iterator<true>& BinaryTree<Key,Value>::Iterator<false>::operator++()
{
...
} //line 211
And the errors I get are:
//normal constructor
binarytree.h(126) : error C3860: template argument list following class template name must list parameters in the order used in template parameter list
binarytree.h(126) : error C3855: 'BinaryTree<Key,Value>::Iterator<_Reverse>': template parameter '_Reverse' is incompatible with the declaration
binarytree.h(126) : error C2977: 'BinaryTree<Key,Value>::Iterator<_Reverse>' : too many template arguments
binarytree.h(118) : error C2952: 'BinaryTree<Key,Value>::Iterator<_Reverse>::Iterator' : template declaration missing template parameter list
//copy constructor
binarytree.h(132) : error C2244: 'BinaryTree<Key,Value>::Iterator<_Reverse>::{ctor}' : unable to match function definition to an existing declaration
definition
'BinaryTree<Key,Value>::Iterator<_Reverse>::Iterator(const BinaryTree<Key,Value>::Iterator<_Reverse> &)'
existing declarations
'BinaryTree<Key,Value>::Iterator<_Reverse>::Iterator(BinaryTree<Key,Value> *,bool)'
'BinaryTree<Key,Value>::Iterator<_Reverse>::Iterator(const BinaryTree<Key,Value>::Iterator<_Reverse> &)' //isn't this one clearly identical?
//operator++ - template specialisations
binarytree.h(196) : error C2244: 'BinaryTree<Key,Value>::Iterator<_Reverse>::operator ++' : unable to match function definition to an existing declaration
definition
'BinaryTree<Key,Value>::?$Iterator@$0A@ &BinaryTree<Key,Value>::Iterator<false>::operator ++(void)'
existing declarations
'BinaryTree<Key,Value>::Iterator<_Reverse> BinaryTree<Key,Value>::Iterator<_Reverse>::operator ++(int)'
'BinaryTree<Key,Value>::Iterator<_Reverse> &BinaryTree<Key,Value>::Iterator<_Reverse>::operator ++(void)'
binarytree.h(211) : error C2244: 'BinaryTree<Key,Value>::Iterator<_Reverse>::operator ++' : unable to match function definition to an existing declaration
definition
'BinaryTree<Key,Value>::?$Iterator@$00 &BinaryTree<Key,Value>::Iterator<true>::operator ++(void)'
existing declarations
'BinaryTree<Key,Value>::Iterator<_Reverse> BinaryTree<Key,Value>::Iterator<_Reverse>::operator ++(int)'
'BinaryTree<Key,Value>::Iterator<_Reverse> &BinaryTree<Key,Value>::Iterator<_Reverse>::operator ++(void)'
As far as I can tell, every single member function has one of these three error groups.
I could potentially solve all of these problems by removing the templated paramater of Iterator, making a second class ReverseIterator which derives and overrides the necessary functions. But I'd prefer to fix it this way, to help me understand what's going wrong.
EDIT: Could somebody fix the code tags? Doesn't seem to be working like I'd expect.
EDIT2: Okay, the second template instruction worked flawlessly. However it seems that the template specialisation errors are occurring because you aren't allowed to specialise an inner class if you don't specialise the outer class. I can work around this, but it means I'm relying on the compiler optimising out certain things. For example, instead of writing:
template <class Key,class Value>
inline bool BinaryTree<Key,Value>::Iterator<false>::DoStuff()
{
return FalseCode();
}
template <class Key,class Value>
inline bool BinaryTree<Key,Value>::Iterator<true>::DoStuff()
{
return TrueCode();
}
I've used:
template <class Key,class Value>
template <bool Reverse>
inline bool BinaryTree<Key,Value>::Iterator<Reverse>::DoStuff()
{
if(Reverse) //hopefully is optimised out; at compile time is either true or false
{
return TrueCode();
}
return FalseCode();
}
I can't help but think that more complex situations might result in the compiler not omitting an unecessary branch. I guess that depends on the compiler however.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
由于这是两个独立的模板类,因此应该是这样的:
但请注意,以下划线开头的变量通常是为编译器的实现保留的。
Since these are two independent template classes, it should be for example like this:
but take a note that a variables starting with the underscore are usually reserved for the compiler's implementation.