Just a quick question - I was wondering if there's any reason why you're
not allowed to shadow template parameters?
e.g.
template <typename T>
struct S
{
typedef T T;
};
I've found it to be quite a useful way of providing access to the
template parameter in certain cases, e.g.
template <typename U>
void f(U u)
{
// e.g. If an S<int> is passed in, we can use typename U::T to
// access the int template parameter
}
VC++ 2005 (apparently incorrectly) allows me to do it, but it gets
flagged up as an error when I compile the same code with g++ (Comeau
also has a problem with it, so I strongly suspect g++ is getting it
right). Is there an alternative way to achieve the same thing without
renaming either the template parameter or the typedef? And is there a
reason why this should be impossible?
Cheers,
Stu
IMO you can, at a nested scope. On the same level you can't because
identifier T is already taken. Use a different name.
typedef T FirstArg;
> I've found it to be quite a useful way of providing access to the template
> parameter in certain cases, e.g.
>
> template <typename U>
> void f(U u)
> {
> // e.g. If an S<int> is passed in, we can use typename U::T to
> // access the int template parameter
> }
Then you can do that.
> VC++ 2005 (apparently incorrectly) allows me to do it, but it gets flagged
> up as an error when I compile the same code with g++
It probably follows from the relax rule of VC that allows "redundant"
typedefs (multiple typedefs to the same name, until they all refer to the
same type).
> (Comeau also has a problem with it, so I strongly suspect g++ is getting
> it right). Is there an alternative way to achieve the same thing without
> renaming either the template parameter or the typedef?
Why is that a problem? Change your code at one place:
template <typename T1>
struct S
{
typedef T1 T;
};
and all the rest shall work fine. (I'm guessing without try...)
But T is just a name you created, what is so special about it? Meanwhile it
is not part of anything beyond the block right after it -- i.e.
template <typename T>
struct S
{
void foo();
};
template <typename T1> // can use any name, and T has no meaning...
void S<T1>::foo() {}
Ok, makes sense.
>> (Comeau also has a problem with it, so I strongly suspect g++ is
>> getting it right). Is there an alternative way to achieve the same
>> thing without renaming either the template parameter or the typedef?
>
> Why is that a problem? Change your code at one place:
>
> template <typename T1>
> struct S
> {
> typedef T1 T;
> };
>
> and all the rest shall work fine. (I'm guessing without try...)
You also have to change it for all the function definitions, which is a
mild pain - but it's not impossible to change, you're right. I was just
wondering why it was necessary really.
> But T is just a name you created, what is so special about it?
> Meanwhile it is not part of anything beyond the block right after it --
> i.e.
>
> template <typename T>
> struct S
> {
> void foo();
> };
>
> template <typename T1> // can use any name, and T has no meaning...
> void S<T1>::foo() {}
This is basically what I've ended up doing (e.g. in an image class, I'm
using PixelType within the class and Pixel as the public typedef) - but
it just seems slightly unnecessary.
No worries, anyway :-)
Stu
Why?
Actually you're right, aren't you? :-) Silly me. Ok, maybe I'm whipping
up a storm in a teacup in that case.
Cheers,
Stu