Actually I’ve a problem with compiling some library with intel compiler.
This same library has been compiled properly with g++.
Problem is caused by templates.
What I’d like to understand is the declaration of
**typename** as not template function parameter and variable declaration inside function body
example:
void func(typename sometype){..
...
typename some_other_type;
..
}
Compilation this kind of code produce following errors (intel),(gcc doesn’t claim):
I’ve got following errors
../../../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())
What I’d like to understand is the usage of the typename inside the body of functions, parameter declarations.
ex.:
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());
}
in different file I’ve:
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;**
You need to use
typenamefor 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
typedefdefiningbarbaris one that requires atypenamein 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::baris a type. For all it know, I might intentbazto be instantiated with types like this onein which case
Foo::barwould refer to an object, not a type, and the definition ofbaz::barwould be syntactic nonsense. Without knowing whetherFoo::barrefers to a type, the compiler has no chance to check anything withinbazthat’s directly or indirectly usingbarbarfor even the most stupid typos untilbazis instantiated. Using the propertypename,bazlooks like this:Now the compiler at least knows that
Foo::baris supposed to be the name of a type, which makesbarbara 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::barit doesn’t know what it is, sobar<Foocould just as well be a comparison, leaving the compiler confused about the trailing>. Here, too, you need to give the compiler a hint thatFoo::baris 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
typenameor atemplate.