Connecting Tech Pros Worldwide Forums | Help | Site Map

function template overloading and typedef in GCC

Arkadiy Vertleyb
Guest
 
Posts: n/a
#1: Jul 19 '05
Hi all,

I am having a problem trying to overload a function template, based on
a typedef, such as:

template<class T>
struct A
{};

template<class T>
struct B
{
typedef A<T> type;
};

template<class T>
void foo(const typename B<T>::type&)
{}

void bar()
{
foo(B<int>::type());
}

g++ 3.3.1 complains at the above code with the following message:
no matching function for call to `foo(A<int>)'

Similar code works with no problem in VC6.

Am I missing something?

Thanks in advance,

Arkadiy



Gianni Mariani
Guest
 
Posts: n/a
#2: Jul 19 '05

re: function template overloading and typedef in GCC


Arkadiy Vertleyb wrote:[color=blue]
> Hi all,
>
> I am having a problem trying to overload a function template, based on
> a typedef, such as:
>
> template<class T>
> struct A
> {};
>
> template<class T>
> struct B
> {
> typedef A<T> type;
> };
>
> template<class T>
> void foo(const typename B<T>::type&)
> {}
>
> void bar()
> {
> foo(B<int>::type());
> }
>
> g++ 3.3.1 complains at the above code with the following message:
> no matching function for call to `foo(A<int>)'
>
> Similar code works with no problem in VC6.
>
> Am I missing something?
>[/color]

Even if this is not allowed by the standard (which I think it is given
some things I've seen - just a hunch) the error message is totally wrong.

Besides:

foo<int>(B<int>::type());

compiles fine.

I suggest you post a bug on gcc. Before you do, you might want to try a
gcc 3.4 devel snapshot. Some template things (like this) have been
fixed in the development branch.

tom_usenet
Guest
 
Posts: n/a
#3: Jul 19 '05

re: function template overloading and typedef in GCC


On 25 Sep 2003 19:27:16 -0700, vertleyb@hotmail.com (Arkadiy Vertleyb)
wrote:
[color=blue]
>Hi all,
>
>I am having a problem trying to overload a function template, based on
>a typedef, such as:
>
>template<class T>
>struct A
>{};
>
>template<class T>
>struct B
>{
> typedef A<T> type;
>};
>
>template<class T>
>void foo(const typename B<T>::type&)[/color]

The above contains a non-deducable context (in this case, a nested
type). This means that calls to the function cannot rely on template
argument deduction, but must use explicit template argument
specification.

The reason this is non-deducable is that the mapping from nested type
to containing type is not in general one-to-one. Often many different
Ts would give the same B<T>::type (think specialization of B).
[color=blue]
>{}
>
>void bar()
>{
> foo(B<int>::type());[/color]

foo<int>(B<int>::type());
[color=blue]
>}[/color]
[color=blue]
>g++ 3.3.1 complains at the above code with the following message:
>no matching function for call to `foo(A<int>)'[/color]

Right.
[color=blue]
>Similar code works with no problem in VC6.[/color]

Yes, this is a bizarre "feature" of VC6 that it deduces this kind of
non-deducable context.
[color=blue]
>Am I missing something?[/color]

Just that VC6 is very old and non-standard.

Tom
Gianni Mariani
Guest
 
Posts: n/a
#4: Jul 19 '05

re: function template overloading and typedef in GCC


tom_usenet wrote:[color=blue]
> On 25 Sep 2003 19:27:16 -0700, vertleyb@hotmail.com (Arkadiy Vertleyb)
> wrote:
>
>[color=green]
>>Hi all,
>>
>>I am having a problem trying to overload a function template, based on
>>a typedef, such as:
>>
>>template<class T>
>>struct A
>>{};
>>
>>template<class T>
>>struct B
>>{
>> typedef A<T> type;
>>};
>>
>>template<class T>
>>void foo(const typename B<T>::type&)[/color]
>
>
> The above contains a non-deducable context (in this case, a nested
> type).[/color]


What's non-deductible about it ?

const typename B<T>::type& <<>> B<int>::type

infers T is int. right ?

How does the standard define non-deductible ?

I must admit, I've never come across this kind of problem, so I really
don't know. Time to brush up ...


tom_usenet
Guest
 
Posts: n/a
#5: Jul 19 '05

re: function template overloading and typedef in GCC


On 26 Sep 2003 14:09:31 GMT, Gianni Mariani <gi2nospam@mariani.ws>
wrote:
[color=blue]
>tom_usenet wrote:[color=green]
>> On 25 Sep 2003 19:27:16 -0700, vertleyb@hotmail.com (Arkadiy Vertleyb)
>> wrote:
>>
>>[color=darkred]
>>>Hi all,
>>>
>>>I am having a problem trying to overload a function template, based on
>>>a typedef, such as:
>>>
>>>template<class T>
>>>struct A
>>>{};
>>>
>>>template<class T>
>>>struct B
>>>{
>>> typedef A<T> type;
>>>};
>>>
>>>template<class T>
>>>void foo(const typename B<T>::type&)[/color]
>>
>>
>> The above contains a non-deducable context (in this case, a nested
>> type).[/color]
>
>
>What's non-deductible about it ?[/color]

It attempts to deduce a template parameter from the type of a typedef
of the template. 14.8.2.4/4 is the relevent bit of the standard.
[color=blue]
>const typename B<T>::type& <<>> B<int>::type
>
>infers T is int. right ?[/color]

No, and the deduction can't even reliably be made. e.g.

template<>
struct B<float>
{
typedef A<int> type; //whoops, now which B?
};

Of course, this could just cause an ambiguity error, as it does in
VC6. However, the mapping from inner type to template parameter is not
always many-to-one, so the committee decided to forbid it.
[color=blue]
>
>How does the standard define non-deductible ?[/color]

Read up on nondeduced contexts.

Tom
Arkadiy Vertleyb
Guest
 
Posts: n/a
#6: Jul 19 '05

re: function template overloading and typedef in GCC


Hi guys,

Thanks for your responce.

Come to think about it, I do realize that overloading on a nested
typedef in this context (at least in my case) doesn't make a lot of
sense. The nested typedef may after all resolve to different types,
like:

template<class T>
struct A1
{};

template<class T>
struct A2
{};

template<class T>
struct B
{
// something like:
typedef select<some_condition_based_on_T, A1<T>, A2<T> >::type type;
};

For both A1 and A2 I need to define a separate overloaded function.
So I actually have to overload on A1<T> and A2<T>, rather than on
B<T>::type.

Regards,

Arkadiy


tom_usenet <tom_usenet@hotmail.com> wrote in message news:<9ji8nvoe0g7mi41f53juinh9iena9rhq0v@4ax.com>. ..[color=blue]
> On 26 Sep 2003 14:09:31 GMT, Gianni Mariani <gi2nospam@mariani.ws>
> wrote:
>[color=green]
> >tom_usenet wrote:[color=darkred]
> >> On 25 Sep 2003 19:27:16 -0700, vertleyb@hotmail.com (Arkadiy Vertleyb)
> >> wrote:
> >>
> >>
> >>>Hi all,
> >>>
> >>>I am having a problem trying to overload a function template, based on
> >>>a typedef, such as:
> >>>
> >>>template<class T>
> >>>struct A
> >>>{};
> >>>
> >>>template<class T>
> >>>struct B
> >>>{
> >>> typedef A<T> type;
> >>>};
> >>>
> >>>template<class T>
> >>>void foo(const typename B<T>::type&)
> >>
> >>
> >> The above contains a non-deducable context (in this case, a nested
> >> type).[/color]
> >
> >
> >What's non-deductible about it ?[/color]
>
> It attempts to deduce a template parameter from the type of a typedef
> of the template. 14.8.2.4/4 is the relevent bit of the standard.
>[color=green]
> >const typename B<T>::type& <<>> B<int>::type
> >
> >infers T is int. right ?[/color]
>
> No, and the deduction can't even reliably be made. e.g.
>
> template<>
> struct B<float>
> {
> typedef A<int> type; //whoops, now which B?
> };
>
> Of course, this could just cause an ambiguity error, as it does in
> VC6. However, the mapping from inner type to template parameter is not
> always many-to-one, so the committee decided to forbid it.
>[color=green]
> >
> >How does the standard define non-deductible ?[/color]
>
> Read up on nondeduced contexts.
>
> Tom[/color]
Closed Thread