From: Dimitar on
Vitaly wrote:
> Hi,
>
> Dimitar wrote
>
> > template <template <class> class Search >
> > class Test : public Search< Test<Search> > {
> > public:
> > typedef Test<Search> Parent_t;
> > };
> >
> > template <class Host>
> > class Y {
> > public:
> > void Search();
> > };
> >
> > class CallManager : public Test<Y> { };
> >
>
> > Did you actually try to create instance of CallManager? If you did not
> > probably this is why it compiled.
>
> Yes, of course. I created the instance. It's not a problem for gcc,
> for example.
>
> > I think Test<Y> is not correct. Y is parameterized class and you have
> > to specify value for the template parameter.
>
> Why? What do I have? 1) class Test with template template parameter
> called Search. 2) template Y. 3) template Test is instanstiated by
> template Y.
>
> This is correct, it seems to me.

Yes you are right about the template template parameter.
Never mind my comment.

The code compiles with VC++ 7 if it is like this:

template <template <class> class Search >
class Test : public Search< Test<Search> > {
public:
typedef Test Parent_t;
};

which is funny because there is Test<Search> two lines above and it
does not complain about it.

Dimitar


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Michael Mehlich on
The source code as presented below is C++ standard conformant.

However, VC++ does not perform two-phase lookup as required by
the C++ standard, but essentially performs all name resolution
at template instantiation time.

I.e., when VC++ looks up Search from within the body of an instance
of Test, the method named Search from the base class is found first,
shadowing the template parameter of the same name. Thus, Test<Search>
becomes ill-formed.

This is a problem for every C++ compiler not implementing two-phase
lookup for templates.

To ensure compilability of source code with different compilers, you
should therefore ensure that your code does not rely on a particular
behavior (two-phase lookup vs. lookup on template instantiation only)
of name lookup for templates.

--
Michael


Vitaly wrote:
> Hi,
>
> Dimitar wrote
>
>
>>template <template <class> class Search >
>>class Test : public Search< Test<Search> > {
>>public:
>> typedef Test<Search> Parent_t;
>>};
>>
>>template <class Host>
>>class Y {
>>public:
>> void Search();
>>};
>>
>>class CallManager : public Test<Y> { };
>>
>
>
>>Did you actually try to create instance of CallManager? If you did not
>>probably this is why it compiled.
>
>
> Yes, of course. I created the instance. It's not a problem for gcc,
> for example.
>
>
>>I think Test<Y> is not correct. Y is parameterized class and you have
>>to specify value for the template parameter.
>
>
> Why? What do I have? 1) class Test with template template parameter
> called Search. 2) template Y. 3) template Test is instanstiated by
> template Y.
>
> This is correct, it seems to me.
>
> And the most interesting thing - if I rename Search memeber function of
> Y to (for example) MySearch, VC++ behavior becomes the same as gcc and
> comeau behavior - it compiles the code without errors and warnings.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Vladimir Marko on
Vitaly wrote:
> The code:
>
> template <template <class> class Search >
> class Test : public Search< Test<Search> > {
> public:
> typedef Test<Search> Parent_t;
> };
>
> template <class Host>
> class Y {
> public:
> void Search();
> };
>
> class CallManager : public Test<Y> { };
>
> This code successfully compiled by gcc and comeau. But if I try to
> compile it with VC++ (Visual Studio 2003 or Visual Studio 2005, does no
> matter) I get the follwoing error:
>
>
> error C2975: 'Search' : invalid template argument for 'Test', expected
> compile-time constant expression
> h:\test\test\test\test.cpp(18) : see reference to class
> template instantiation 'Test<Search>' being compiled
> with
> [
> Search=Y
> ]

It is a VC++ bug. Since Search<Test<Search> > is a _dependent_ type
a name from that class cannot hide a name from the template or its
enclosing scopes (see 14.6.2/4).

Note, however, that if a base class that is a non-dependent type would
contain the name in question the template parameter name would be
hidden by the name in the base class. Thus it is preferrable to use
a naming scheme which prevents such conflicts.

Cheers

Vladimir Marko


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]