-2

Possible Duplicate:
Where and why do I have to put the “template” and “typename” keywords?

I'm trying to use traits for the first time to enable me to succinctly associate related types in some generic routines. However I'm struggling with the syntax and Googling doesn't seem to turn up any simple examples for implementing this kind of thing. Here is condensed example of what I have currently:

template <typename T> struct foo_traits { };

template<> struct foo_traits<int> {
    typedef unsigned char T2; // sub-type for int specialisation of foo_traits
};

template <typename T> T foo(void)
{
    typedef foo_traits<T> traits_type; // OK
    typedef traits_type::T2 T2; // error here: "Too few template-parameter-lists"

    T i
    T2 j;

    // ...
}

What is the correct way to get the T2 typedef from foo_traits so that I can use it in my generic template function foo ?

Community
  • 1
  • 1
Paul R
  • 208,748
  • 37
  • 389
  • 560
  • 2
    Another duplicate... (hint -- you need `typename`). Let me find the FAQ item... – Mankarse Jan 24 '12 at 10:58
  • Thanks - I did try searching SO first of course, but I'd appreciate it if you can find a relevant duplicate – Paul R Jan 24 '12 at 11:00
  • Also, how do you expect the traits to work for the general case? For any `T` other than `int`, `traits_type::T2` will simply not exist. – Mankarse Jan 24 '12 at 11:01
  • Thanks, yes, I understand that - this is just a condensed example to illustrate the problem - I'll have a number of different traits specialisations to handle all the possible cases. – Paul R Jan 24 '12 at 11:04
  • ...and thanks for finding the duplicate ! – Paul R Jan 24 '12 at 11:06

1 Answers1

2

Odd error message, but you really have to tell the compiler that the nested T2 is supposed to be a type name

typedef typename traits_type::T2 T2;
Bo Persson
  • 90,663
  • 31
  • 146
  • 203
  • Thanks - that fixes the problem. I'm not sure *why* it fixes it though - it's probably time to invest in a decent book about this kind of thing - any suggestions ? – Paul R Jan 24 '12 at 11:03
  • 1
    _C++ Templates_ by Vandevoorde & Josuttis is good. I'm not sure if anything is available yet which also covers the C++11. – Useless Jan 24 '12 at 11:12
  • @Useless: thanks for the book recommendation - now added to my Amazon "wish list" ! – Paul R Jan 24 '12 at 11:41
  • 1
    @Paul - The reason for `typename` is that you just *might* have some specialisations where `T2` is a type namn and some where it is some thing else, a variable perhaps. You have to tell the compiler that inside `foo` it should always expect a type name, because the default is to expect that it is not. – Bo Persson Jan 24 '12 at 12:13
  • @Bo: thanks for the further clarification - as a long-time C programmer this metaprogramming stuff is making me feel a little queasy, but I'm getting there. ;-) – Paul R Jan 24 '12 at 12:28
  • 1
    @PaulR as an extra bit of info, the problem is that templates are processed in two passes. During the first pass the template arguments are unbound, But the compiler still needs to make sense of the code (to some extent, it can leave a couple of things behind). It is during that first pass that you are getting the error, the compiler does not know what `traits_type::T2` will be after type substitution, and the standard tells it to assume that it is a member. At this point, a member does not make sense in the grammar and the compiler bails out. Adding the `typename` you are saying it is a type. – David Rodríguez - dribeas Jan 24 '12 at 13:06
  • @David: thanks for that - from what you say I think I just have to remember that `typename` applies to `traits_type::T2`, i.e. think of it as one entity: `typename traits_type::T2` – Paul R Jan 24 '12 at 13:20
  • @PaulR the specific rule roughly says that you suture `typename` whenever accessing a type through a dependent identifier, where dependent identifier means that the identifier depends on the arguments to the template. Since `traits_type` depends on `T`, and you want to access the nested type `T2`, you need the keyword. – David Rodríguez - dribeas Jan 25 '12 at 04:27