模板问题(“类型名称”不是模板函数参数)
实际上,我在使用英特尔编译器编译某些库时遇到问题。
该库已使用 g++ 正确编译。
问题是由模板引起的。
我想了解的是声明
**typename**
不是模板函数参数和函数体内的变量声明
示例:
void func(typename sometype){..
...
typename some_other_type;
..
}
编译此类代码会产生以下错误(intel),(gcc 不声明): 我有以下错误
../../../libs/log/src/attribute_set.cpp(415): error: no operator "!=" matches these operands
operand types are: boost::log_st::basic_attribute_set<wchar_t>::iter<'\000'> != boost::log_st::basic_attribute_set<wchar_t>::iter<'\000'>
while (begin != end)
^
detected during instantiation of "void boost::log_st::basic_attribute_set<CharT>::erase(boost::log_st::basic_attribute_set<CharT>::iter<'\000'>, boost::log_st::basic_attribute_set<CharT>::iter<'\000'>) [with CharT=wchar_t]" at line 438
../../../boost/log/attributes/attribute_set.hpp(115): error: no operator "!=" matches these operands
operand types are: boost::log_st::basic_attribute_set<wchar_t>::iter<'\000'> != boost::log_st::basic_attribute_set<wchar_t>::iter<'\000'>
if (it != m_pContainer->end())
我想了解的是函数体内的类型名、参数声明的用法。
例如:
template< typename CharT >
struct basic_attribute_values_view< CharT >::implementation
{
public:
..
..
void adopt_nodes( **typename attribu**te_set_type::const_iterator& it, **typename attribut**e_set_type::const_iterator end)
{
for (; it != end; ++it)
push_back(it->first, it->second.get());
}
在不同的文件中我有:
template< typename CharT >
class basic_attribute_set
{
friend class basic_attribute_values_view< CharT >;
//! Self type
typedef basic_attribute_set< CharT > this_type;
public:
//! Character type
typedef CharT char_type;
//! String type
typedef std::basic_string< char_type > string_type;
//! Key type
typedef basic_slim_string< char_type > key_type;
//! Mapped attribute type
typedef shared_ptr< attribute > mapped_type;
//! Value type
typedef std::pair< const key_type, mapped_type > value_type;
//! Allocator type
typedef std::allocator< value_type > allocator_type;
//! Reference type
**typedef typename allocator_type::reference reference;**
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
![扫码二维码加入Web技术交流群](/public/img/jiaqun_03.jpg)
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您需要使用
typename
来表示所谓的“依赖类型”。这些类型依赖于模板参数,并且在实例化模板之前是未知的。最好用一个例子来解释:定义 barbar 的
typedef
需要一个typename
以便编译器能够检查在使用具体类型实例化之前,存在明显语法错误的模板。原因是,当编译器第一次看到模板时(当它还没有使用具体模板参数实例化时),编译器不知道Foo::bar
是否是一个类型。据我所知,我可能打算使用像这样的类型实例化baz
,在这种情况下
Foo::bar
将引用一个对象 ,而不是类型,并且baz::bar
的定义在语法上是无意义的。在不知道Foo::bar
是否引用类型的情况下,编译器没有机会检查baz
中直接或间接使用barbar
的任何内容即使是最愚蠢的拼写错误,直到实例化baz
为止。使用正确的typename
,baz
看起来像这样:现在编译器至少知道
Foo::bar
应该是 a 的名称type,这也使barbar
成为类型名称。因此f()
的声明在语法上也是正确的。顺便说一句,模板而不是类型也存在类似的问题:
当编译器“看到”
Foo::bar
时,它不知道它是什么,所以bar > 也可以是一个比较,让编译器对尾随的
>
感到困惑。在这里,您还需要向编译器提示Foo::bar
应该是模板的名称:注意:值得注意的是 Visual C++ 仍然没有实现正确的两阶段查找(本质上:在模板被实例化之前,它并不真正检查模板)。因此,它经常接受缺少
typename
或template
的错误代码。You need to use
typename
for so-called "dependent types". Those are types that depend on a template argument and are not known until the template is instantiated. It's probably best explained using an example:That
typedef
definingbarbar
is one that requires atypename
in order for the compiler to be able to check the template for blatant syntactic errors before it is instantiated with a concrete type. The reason is that, when the compiler sees the template for the first time (when it's not instantiated with concrete template parameters yet), the compiler doesn't know whetherFoo::bar
is a type. For all it know, I might intentbaz
to be instantiated with types like this onein which case
Foo::bar
would refer to an object, not a type, and the definition ofbaz::bar
would be syntactic nonsense. Without knowing whetherFoo::bar
refers to a type, the compiler has no chance to check anything withinbaz
that's directly or indirectly usingbarbar
for even the most stupid typos untilbaz
is instantiated. Using the propertypename
,baz
looks like this:Now the compiler at least knows that
Foo::bar
is supposed to be the name of a type, which makesbarbar
a type name, too. So the declaration off()
is syntactical OK, too.By the way, there's a similar problem with templates instead of types:
When the compiler "sees"
Foo::bar
it doesn't know what it is, sobar<Foo
could just as well be a comparison, leaving the compiler confused about the trailing>
. Here, too, you need to give the compiler a hint thatFoo::bar
is supposed to be the name of a template:Beware: Notably Visual C++ still doesn't implement proper two-phase lookup (in essence: it doesn't really check templates until they are instantiated). Therefor it often accepts erroneous code that misses a
typename
or atemplate
.typename
关键字的作用是在不明显的情况下告诉编译器某物是类型名。举个例子:T::foo
是一个类型,意味着我们正在声明一个指针,还是T::foo
是一个静态变量,并且我们正在做乘法?由于编译器在读取模板时不知道 T 可能是什么,因此它不知道这两种情况中哪一种是正确的。
标准规定编译器应假定后一种情况,并且仅将前面带有
typename
关键字的T::foo
解释为类型名,如下所示:The point of the
typename
keyword is to tell the compiler that something is a typename, in situations where it's not obvious. Take this example:Is
T::foo
a type, meaning we are declaring a pointer, or isT::foo
a static variable, and we are doing a multiplication?Since the compiler has no idea of what T could be at the time it reads the template, it has no idea which of the two cases is correct.
The standard dictates that the compiler should assume the latter case, and only interpret
T::foo
as a typename if it is preceded by thetypename
keyword, like this:根据您的代码:
如果上述代码不是模板的一部分,则无法使用 g++ 编译它,除非旧版本的 g++。
根据我的经验,FC9 或 GNU C/++ 4.2x 版本会将其报告为错误,它会抱怨:
而 FC8 或 GNU C/++ 4.1x 可能不会。
请参阅
更多模板和类型名称示例。
Upon your code:
If the above code is not a part of a template, then it cannot be compiled using g++, unless the old version of g++.
As my experienced, FC9 or GNU C/++ version 4.2x will report it as an error, it'll complain:
while FC8 or GNU C/++ 4.1x may not.
Please see
for more template and typename examples.