typedef and template parameter in C++

Started by
4 comments, last by bulgurmayo 16 years ago
Hi, is the following piece of code valid Cpp. Or am I exposing myself to the dangers of undefined behaviour :

template <typename T>
class A
{
public:
  typedef boost::ptr_container< T >    Container;
  typedef Container::value_type        value_type;
  typedef Container::reference         reference;
  typedef Container::const_reference   const_reference;
  typedef Container::size_type         size_type;
  typedef Container::iterator          iterator;
  typedef Container::const_iterator    const_iterator;

...

};

The thing I am worried about is this :

  typedef boost::ptr_container< T >    Container;

Advertisement
The line in question is perfectly legal, you shouldn't worry :)
there needs to be a typename in there depending on how conformant your compiler is - maybe not vs6

template< class T>  struct C {    typedef ptr_vector< T>  container;     typedef typename container::value_type value_type; };


also consider derivation - its not necessarily right but depending on use can give you the typing information

template< class T>  struct B : public ptr_vector< T>  {}; B< int>::value_type elt;








Quote:Original post by bulgurmayo
is the following piece of code valid Cpp. Or am I exposing myself to the dangers of undefined behaviour

It's not undefined behaviour. It's perfectly defined. Your code is ambiguous and will not compile under a conforming compiler. As mentioned above, you need to qualify the dependant names with a 'typename' decorator to disambiguate during two-phase name lookup.

You see a lot of exactly that sort of construct all through the standard library code. It's not only OK but the C++ gods beheld it and it was good.

--smw

Stephen M. Webb
Professional Free Software Developer

Good catch chairthrower.

To elaborate, since the type of Container depends on a template parameter passed to "us", all it's member classes and types are what are known as "dependent typenames" and require the use of the typename keyword:
template <typename T>class A{public:  typedef boost::ptr_container< T >             Container;  typedef typename Container::value_type        value_type;  typedef typename Container::reference         reference;  typedef typename Container::const_reference   const_reference;  typedef typename Container::size_type         size_type;  typedef typename Container::iterator          iterator;  typedef typename Container::const_iterator    const_iterator;...};


Static functions/variables don't need to be qualified, but member templates also have special syntax:

typedef typename Container::allocator_type::template rebind<short>::other::template rebind<int>::other int_allocator;

Quick explaination: Since the exact type of Container depends on a template parameter of our context, T, a given member... say, Container::foo, could be a static variable for T=char, a static function for T=short, a typedef for T=int, and a template for T=float. The typename keyword is our way of saying that a given expression ends in a type... in this case, that:

Container::...::other is a type.

Templates are slightly more complicated: We need to use the template keyword at each point they occur, which is why you see it multiple times in my convoluted example, unlike typename:

Container::...::template rebind is a template. Both times.

HTH
Thanks for the explanations. After a little search I found this : http://www.parashift.com/c++-faq-lite/templates.html#faq-35.18

Also the reason why I am not using derivation is because I want to create read-only container.

This topic is closed to new replies.

Advertisement