Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Shadowing template parameters

2 views
Skip to first unread message

Stuart Golodetz

unread,
Nov 30, 2009, 7:39:54 AM11/30/09
to
Hi,

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

Balog Pal

unread,
Nov 30, 2009, 8:24:59 AM11/30/09
to
"Stuart Golodetz"

> Hi,
>
> 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;
> };

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() {}

Stuart Golodetz

unread,
Nov 30, 2009, 8:27:00 AM11/30/09
to
Balog Pal wrote:
> "Stuart Golodetz"
>> Hi,
>>
>> 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;
>> };
>
> 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).

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

Balog Pal

unread,
Nov 30, 2009, 8:32:08 AM11/30/09
to
"Stuart Golodetz"
>>> (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

Why?


Stuart Golodetz

unread,
Nov 30, 2009, 8:44:00 AM11/30/09
to

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

0 new messages