实际上我在使用intel编译器编译某些库时遇到了问题。
使用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())
我想要了解的是在函数体内使用typename,参数声明。
例如:
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;**
答案 0 :(得分:13)
您需要将typename
用于所谓的“依赖类型”。这些是依赖于模板参数的类型,在模板实例化之前不知道。最好用一个例子来解释:
struct some_foo {
typedef int bar;
};
template< typename Foo >
struct baz {
typedef Foo::bar barbar; // wrong, shouldn't compile
barbar f(); // would be fine if barbar were a type
// more stuff...
};
定义typedef
的{{1}}是需要barbar
的{{1}},以便编译器能够在之前检查模板是否存在明显的语法错误用具体类型实例化。原因是,当编译器第一次看到模板时(当它还没有使用具体的模板参数进行实例化时),编译器不知道typename
是否是一个类型。尽管如此,我可能会将Foo::bar
用这样的类型实例化
baz
在这种情况下,struct some_other_foo {
static int bar;
};
将引用对象,而不是类型,Foo::bar
的定义将是语法无意义的。在不知道baz::bar
是否引用类型的情况下,编译器没有机会使用Foo::bar
直接或间接检查baz
内的任何内容,即使是最愚蠢的拼写错误,直到barbar
为止实例化。使用正确的baz
,typename
如下所示:
baz
现在,编译器至少知道template< typename Foo >
struct baz {
typedef typename Foo::bar barbar;
barbar f();
// more stuff...
};
应该是类型的名称,这也使Foo::bar
成为类型名称。所以barbar
的声明也是合法的。
顺便说一下,模板而不是类型存在类似的问题:
f()
当编译器“看到”template< typename Foo >
struct baz {
Foo::bar<Foo> create_wrgl(); // wrong, shouldn't compile
};
时它不知道它是什么,所以Foo::bar
也可能是一个比较,让编译器对尾随bar<Foo
感到困惑。在这里,您还需要为编译器提供>
应该是模板名称的提示:
Foo::bar
注意:值得注意的是,Visual C ++仍然没有实现正确的两阶段查找(实质上:在实例化之前它并不真正检查模板)。因此,它经常接受错过template< typename Foo >
struct baz {
Foo::template bar<Foo> create_wrgl();
};
或typename
的错误代码。
答案 1 :(得分:4)
typename
关键字的意思是告诉编译器某些东西是一个类型名称,在不明显的情况下。举个例子:
template<typename T>
void f()
{
T::foo * x;
}
T::foo
是一个类型,意味着我们正在声明一个指针,或者T::foo
是一个静态变量,我们正在进行乘法运算?
由于编译器在读取模板时不知道T可能是什么,因此它不知道这两种情况中的哪一种是正确的。
标准规定编译器应该采用后一种情况,并且只有T::foo
作为类型名称解释,如果它前面有typename
关键字,如下所示:
template<typename T>
void f()
{
typename T::foo* x; //Definitely a pointer.
}
答案 2 :(得分:0)
根据您的代码:
void func(typename sometype)
{
.....typename some_other_type;
..
}
如果上面的代码不是模板的一部分,那么除非旧版本的g ++,否则无法使用g ++编译。
根据我的经验,FC9或GNU C / ++版本4.2x会将其报告为错误,它会抱怨:
typename only can be used in template code
虽然FC8或GNU C / ++ 4.1x可能没有。
请参阅
http://code.google.com/p/effocore/source/browse/trunk/devel/effo/codebase/addons/inl/include/ringed_inl.h
and
http://code.google.com/p/effocore/source/browse/trunk/devel/effo/codebase/addons/inl/include/cont_inl.h
了解更多模板和typename示例。