tags:

views:

52

answers:

1

I've been trying to work with templates for a while now and the more I do the less I realise I understand. This latest problem feels like it has unearthed a rather fundamental misunderstanding on my part and I'm starting to think more than ever that, "Right, tomorrow I shouldn't write any code but instead find a library with a good CS section and just read everything they have on templates"! I wonder if in the mean time you can help me.

So, the following code,

template <typename T>    // or replace `typename` with `class`
struct Foo {
    struct Bar {};
    Foo(Bar) {}
};

Foo<float>::Bar x;
Foo<int> y (x);

doesn't compile since x is of type Foo<float>::Bar but to construct y we need a Foo<int>::Bar. That's fine, and expected, but now consider the following,

template <int I>
struct Foo {
    struct Bar {};
    Foo(Bar) {}
};

Foo<0>::Bar x;
Foo<1> y (x);

I was hoping/thinking (although, thankfully, not as yet relying on) that x would be of type Foo<0>::Bar and to construct y we would need a Foo<1>::Bar and as such it would not compile - as in the previous example. But it seems that both are in fact of type Foo<int>::Bar and so, this will compile.

So, I wonder, what, first, is the correct terminology to describe this difference between a typename/class parameterized template and an integral type parameterized one, what other differences in behaviour does this entail, and, what method could I use to solve this problem and get the desired behaviour for this simple example so that Foo<0> and Foo<1> will describe incompatible types?

And, before that trip to the library, any links to "essential", online, reading materials on the subject would be welcomed too. Thanks.

+2  A: 

On gcc 4.4.3 your second example fails to compile with the message "error: no matching function for call to 'Foo<1>::Foo(Foo<0>::Bar&)'", which is exactly what you expected to happen.

So you did not misunderstand anything. If this compiles for you, that's non-standard behavior by your compiler.

sepp2k