Cannot invoke a templated ctor

M

Momchil Velikov

The following program produces error at the definition of ``b''. However it
compiles fine the second (supposedly equivalent) form of the templated
constructor. Why the two alternatives aren't equivalent ?

template<class Obj>
struct ptr_to_member
{
typedef void (Obj::* type) ();
};

struct A
{
A (void (*fn) ())
{
}

#if 1
template<class Obj>
A (typename ptr_to_member <Obj>::type fn)
{
}
#else
template<class Obj>
A (void (Obj::* fn) ())
{
}
#endif
};

void foo ()
{
}

struct bar
{
void baz ()
{
}
};

A a (foo);

A b (&bar::baz);
 
D

David B. Held

Momchil Velikov said:
[...]
template<class Obj>
A (typename ptr_to_member <Obj>::type fn)
{
}

This is a non-deducible context.
template<class Obj>
A (void (Obj::* fn) ())
{
}

This context is deducible.

Basically, if the compiler has to instantiate a type to match a
template parameter, then the context is non-deducible (the
compiler is too lazy to do the instantiation, since it could
become arbitrarily complex, and probably lead to weird
recursions in some cases).

Dave
 
C

Chris Theis

David B. Held said:
Momchil Velikov said:
[...]
template<class Obj>
A (typename ptr_to_member <Obj>::type fn)
{
}

This is a non-deducible context.
template<class Obj>
A (void (Obj::* fn) ())
{
}

This context is deducible.

Basically, if the compiler has to instantiate a type to match a
template parameter, then the context is non-deducible (the
compiler is too lazy to do the instantiation, since it could
become arbitrarily complex, and probably lead to weird
recursions in some cases).

Dave

[Just a comment]
Interestingly enough Visual C++ 6.0 (SP5) which is not yet a very standard
compliant compiler in terms of templates, manages to deduce the context.

Chris
 
D

David B. Held

Chris Theis said:
[...]
[Just a comment]
Interestingly enough Visual C++ 6.0 (SP5) which is not yet a very
standard compliant compiler in terms of templates, manages to
deduce the context.

Interesting. Please try this code on it:

template <typename T>
struct identity
{
typedef T type;
};

template <typename T>
void foo(typename identity<T>::type)
{
}

int main()
{
int i;
foo(i);
}

Comeau online gives:

"ComeauTest.c", line 15: error: no instance of function template "foo"
matches the argument list
The argument types that you used are: (int)
foo(i);
^

Note that the identity metafunction is often used explicitly to
suppress deduction, so VC6 is truly broken indeed if it performs
the deduction anyway (but I have a suspicion that it doesn't,
and something else is going on with your test code).

Dave
 
C

Chris Theis

David B. Held said:
Chris Theis said:
[...]
[Just a comment]
Interestingly enough Visual C++ 6.0 (SP5) which is not yet a very
standard compliant compiler in terms of templates, manages to
deduce the context.

Interesting. Please try this code on it:

template <typename T>
struct identity
{
typedef T type;
};

template <typename T>
void foo(typename identity<T>::type)
{
}

int main()
{
int i;
foo(i);
}

Comeau online gives:

"ComeauTest.c", line 15: error: no instance of function template "foo"
matches the argument list
The argument types that you used are: (int)
foo(i);
^

And IMHO it's right.
Note that the identity metafunction is often used explicitly to
suppress deduction, so VC6 is truly broken indeed if it performs
the deduction anyway (but I have a suspicion that it doesn't,
and something else is going on with your test code).

Dave

VC6 compiles the code just fine. Probably I'll give it a try on VC7
sometime.

Chris
 
C

Chris Theis

David B. Held said:
Momchil Velikov said:
[...]
template<class Obj>
A (typename ptr_to_member <Obj>::type fn)
{
}

This is a non-deducible context.
template<class Obj>
A (void (Obj::* fn) ())
{
}

This context is deducible.

Basically, if the compiler has to instantiate a type to match a
template parameter, then the context is non-deducible (the
compiler is too lazy to do the instantiation, since it could
become arbitrarily complex, and probably lead to weird
recursions in some cases).

Dave

Hi Dave, can you give me the exact part of the standard for this, please.

Regards
Chris
 
S

Shane Beasley

Chris Theis said:
VC6 compiles the code just fine. Probably I'll give it a try on VC7
sometime.

FWIW, VC++.NET (aka VC++7) does not accept it. But since VC++6 accepts
it, I don't know why ISO C++ shouldn't also accept it. That is, I
figured it just happened to be difficult or impossible to do, but
VC++6 did it.

Sounds like a topic for comp.std.c++, actually.

- Shane
 
J

Jerry Coffin

[ ... ]
FWIW, VC++.NET (aka VC++7) does not accept it. But since VC++6 accepts
it, I don't know why ISO C++ shouldn't also accept it. That is, I
figured it just happened to be difficult or impossible to do, but
VC++6 did it.

Off the top of my head, I don't remember exactly what you're talking
about, but I guess it doesn't really matter. VC++ 6 simplifies the
language to the point that quite a few ambiguities in the real language
don't exist in its language. An ambiguity results when a particular
expression _could_ be interpreted in one of two possible ways. When/if
the compiler is simply limited to the point that it doesn't recognize
one of those possibilities at all, then what should be ambiguous input
is unambiguous for it. Making the compiler recognize the other
possibility, however, makes the expression ambiguous.
 
D

David B. Held

Chris Theis said:
[...]
Hi Dave, can you give me the exact part of the standard for this,
please.

I wish I could, by my only copy of the standard is on a dead HD,
so I'll have to give you the exact part of the draft standard instead:

14.8.2/9

14.8.2/10:

In a type which contains a nested-name-specifier, template
argument values cannot be deduced for template parameters
used within the nested-name-specifier. [Example:

template<int i, typename T>
T deduce(A<T>::X x, // T is not deduced here
T t, // but T is deduced here
B<i>::Y y); // i is not deduced here

I think paragraph 10 pretty much sums it up (it does for me,
anyway).

I also highly recommend the Vandevoorde/Josuttis text on
templates. It doesn't always make things clear, but it always
makes things precise, and since templates sometimes can't be
clear with any amount of explanation, precision is as good as
it gets. ;>

Dave
 
S

Shane Beasley

Jerry Coffin said:
VC++ 6 simplifies the
language to the point that quite a few ambiguities in the real language
don't exist in its language.

Actually, you're right. It seems that this "trick" only works in the
case where the function parameter is something like

typename foo<T>::type

where foo<T>::type is dependent on T. Frankly, that is rather useless.

Nevermind. :)

- Shane
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,143
Messages
2,570,822
Members
47,368
Latest member
michaelsmithh

Latest Threads

Top