views:

256

answers:

3

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;**
+3  A: 

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:

template<typename T>
void f()
{
    T::foo * x;
}

Is T::foo a type, meaning we are declaring a pointer, or is T::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 the typename keyword, like this:

template<typename T>
void f()
{
    typename T::foo* x; //Definitely a pointer.
}
CAdaker
+5  A: 

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:

struct foo {
  typedef int wrgl;
};

template< typename T >
struct bar {
  typedef T::wrgl blrgl; // wrong, shouldn't compile

  blrgl f(); // fine if `blrgl` is a type

  // more stuff...
};

That second typedef is one that requires a typename 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 the compiler doesn't know whether T::wrgl is a type. For all it know, I might intent bar to be instantiated with types like this one

struct blah {
  static int wrgl;
};

in which case T::wrgl would refer to an object, not a type, and the definition of bar::wrgl would be syntactic nonsense. Without knowing, whether T::wrgl refers to a type, the compiler has no chance to check anything within bar that's directly or indirectly using blrgl for even the most stupid typos until bar is instantiated. Using the proper typename, bar looks like this:

template< typename T >
struct bar {
  typedef typename T::wrgl blrgl;

  blrgl f();

  // more stuff...
};

Now the compiler at least knows that T::wrgl is the name of a type, which makes blrgl a type name, too. So the declaration of f() is syntactical OK, too.

By the way, there's a similar problem with templates instead of types:

template< typename T >
struct bar {
  T::wrgl<T> create_wrgl(); // wrong, shouldn't compile
};

When the compiler "sees" T::wrgl it doesn't know what it is, so wrgl<X could just as well be a comparison. Here, too, you need to give the compiler a hint that T::wrgl is supposed to be the name of a template:

template< typename T >
struct bar {
  T::template wrgl<T> create_wrgl();
};

Note that 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 a template.

sbi
+1 for mention of two-phase lookup. Hence the advice: if possible try to compile your code with at least 2 different compilers.
Francesco
A: 

Upon your code:

void func(typename sometype)
{
    .....typename some_other_type;
    ..
}

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:

typename only can be used in template code

while FC8 or GNU C/++ 4.1x may not.

Please see

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

for more template and typename examples.

EffoStaff Effo