Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > How to pass this template template argument? (MSVC++ 8 error C3200)

Reply
Thread Tools

How to pass this template template argument? (MSVC++ 8 error C3200)

 
 
Niels Dekker - no reply address
Guest
Posts: n/a
 
      01-27-2006
The following attempt to pass my template "Base" as a template template
argument was rejected by Microsoft VC++ 8.0 (2005), while it still works
on VC++ 7.1 (2003). Is it correct C++? And is there a workaround?

template <typename T> class Base
{
};
template <typename U, template <typename> class TempTemp>
class Derived;

template <typename V>
class Derived<V, Base> : public Base<V>
{
public:
template <typename W> void Fun(Derived<W, Base>&) // <-- error!?!
{
}
};

MSVC++ 8.0 says about Fun(Derived<W, Base>&):
error C3200: 'Base<T>' : invalid template argument for template
parameter 'TempTemp', expected a class template
see reference to class template instantiation 'Derived<V,Base>' being
compiled


Kind regards,

Niels Dekker
www.xs4all.nl/~nd/dekkerware
 
Reply With Quote
 
 
 
 
Victor Bazarov
Guest
Posts: n/a
 
      01-28-2006
Niels Dekker - no reply address wrote:
> The following attempt to pass my template "Base" as a template
> template argument was rejected by Microsoft VC++ 8.0 (2005), while it
> still works on VC++ 7.1 (2003). Is it correct C++? And is there a
> workaround?
>
> template <typename T> class Base
> {
> };
> template <typename U, template <typename> class TempTemp>
> class Derived;
>
> template <typename V>
> class Derived<V, Base> : public Base<V>
> {
> public:
> template <typename W> void Fun(Derived<W, Base>&) // <-- error!?!
> {
> }
> };
>
> MSVC++ 8.0 says about Fun(Derived<W, Base>&):
> error C3200: 'Base<T>' : invalid template argument for template
> parameter 'TempTemp', expected a class template
> see reference to class template instantiation 'Derived<V,Base>' being
> compiled
>


I just added this:

int main()
{
Derived<int,Base> di;
Derived<char,Base> dc;
di.Fun(dc);
}

And compiled it successfully with VC++ v8.0.

Please next time post the _complete_ code if you want us to be able
to help you with any particular problem.

V


 
Reply With Quote
 
 
 
 
John Carson
Guest
Posts: n/a
 
      01-28-2006
"Victor Bazarov" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)
> Niels Dekker - no reply address wrote:
>> The following attempt to pass my template "Base" as a template
>> template argument was rejected by Microsoft VC++ 8.0 (2005), while it
>> still works on VC++ 7.1 (2003). Is it correct C++? And is there a
>> workaround?
>>
>> template <typename T> class Base
>> {
>> };
>> template <typename U, template <typename> class TempTemp>
>> class Derived;
>>
>> template <typename V>
>> class Derived<V, Base> : public Base<V>
>> {
>> public:
>> template <typename W> void Fun(Derived<W, Base>&) // <-- error!?!
>> {
>> }
>> };
>>
>> MSVC++ 8.0 says about Fun(Derived<W, Base>&):
>> error C3200: 'Base<T>' : invalid template argument for template
>> parameter 'TempTemp', expected a class template
>> see reference to class template instantiation 'Derived<V,Base>'
>> being compiled
>>

>
> I just added this:
>
> int main()
> {
> Derived<int,Base> di;
> Derived<char,Base> dc;
> di.Fun(dc);
> }
>
> And compiled it successfully with VC++ v8.0.



Strange. It won't compile for me on either VC++ Express 2005 or a Release
Candidate of VS Team System.

--
John Carson


 
Reply With Quote
 
John Carson
Guest
Posts: n/a
 
      01-28-2006
"Niels Dekker - no reply address" <(E-Mail Removed)> wrote in
message news:(E-Mail Removed)
> The following attempt to pass my template "Base" as a template
> template argument was rejected by Microsoft VC++ 8.0 (2005), while it
> still works on VC++ 7.1 (2003). Is it correct C++? And is there a
> workaround?
>
> template <typename T> class Base
> {
> };
> template <typename U, template <typename> class TempTemp>
> class Derived;
>
> template <typename V>
> class Derived<V, Base> : public Base<V>
> {
> public:
> template <typename W> void Fun(Derived<W, Base>&) // <-- error!?!
> {
> }
> };


The workaround is to qualify Base with ::, so that it becomes:

template <typename W> void Fun(Derived<W, ::Base>&)
{
}

As for whether your original code is valid C++, I am inclined to think that
it is but I wouldn't bet my life on it. The strongest indication that the
original code is valid is that Comeau compiles it without complaint.

I believe what is happening is the following. VC++ 8 is reading Base as
Base<V>. In the following simpler example, that would be correct:

template <class V>
class Base
{
Base b; // read this as Base<V>
};

If you wanted to refer to the template Base inside Base, then you could use
::Base.

Where VC++ 8 appears to have gone subtlely wrong is in treating Base in
Derived the same way as it would treat Base in Base. Because Base is a
dependent base (i.e., it depends on V), two phase lookup (as I understand
it) says that it should not be looked up until the template is instantiated.
Thus Base<V> is not seen when Fun is defined, with the result that Base is
treated as a template, so the code compiles. VC++ does not support two phase
lookup, so it does see Base<V> when Fun is defined and hence gives an
error...or at least I think that is the explanation.


--
John Carson


 
Reply With Quote
 
Victor Bazarov
Guest
Posts: n/a
 
      01-28-2006
John Carson wrote:
> "Victor Bazarov" <(E-Mail Removed)> wrote in message
> news:(E-Mail Removed)
>> Niels Dekker - no reply address wrote:
>>> The following attempt to pass my template "Base" as a template
>>> template argument was rejected by Microsoft VC++ 8.0 (2005), while
>>> it still works on VC++ 7.1 (2003). Is it correct C++? And is
>>> there a workaround?
>>>
>>> template <typename T> class Base
>>> {
>>> };
>>> template <typename U, template <typename> class TempTemp>
>>> class Derived;
>>>
>>> template <typename V>
>>> class Derived<V, Base> : public Base<V>
>>> {
>>> public:
>>> template <typename W> void Fun(Derived<W, Base>&) // <-- error!?!
>>> {
>>> }
>>> };
>>>
>>> MSVC++ 8.0 says about Fun(Derived<W, Base>&):
>>> error C3200: 'Base<T>' : invalid template argument for template
>>> parameter 'TempTemp', expected a class template
>>> see reference to class template instantiation 'Derived<V,Base>'
>>> being compiled
>>>

>>
>> I just added this:
>>
>> int main()
>> {
>> Derived<int,Base> di;
>> Derived<char,Base> dc;
>> di.Fun(dc);
>> }
>>
>> And compiled it successfully with VC++ v8.0.

>
>
> Strange. It won't compile for me on either VC++ Express 2005 or a
> Release Candidate of VS Team System.


Compiled for me on Express 2005. Are you sure you used the same code?
-------------- this is from your post
template<typename T> class Base
{
};

template<typename U, template<typename> class TempTemp> class Derived;

template<typename V> class Derived<V, Base> : public Base<V>
{
public:
template <typename W> void Fun(Derived<W, Base>&) // <-- error!?!
{
}
};
// -------------- this I added...
int main()
{
Derived<int,Base> di;
Derived<char,Base> dc;
di.Fun(dc);
}
--------------

V
--
Please remove capital As from my address when replying by mail


 
Reply With Quote
 
John Carson
Guest
Posts: n/a
 
      01-28-2006
"Victor Bazarov" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)
> John Carson wrote:
>>
>> Strange. It won't compile for me on either VC++ Express 2005 or a
>> Release Candidate of VS Team System.

>
> Compiled for me on Express 2005. Are you sure you used the same code?
> -------------- this is from your post
> template<typename T> class Base
> {
> };
>
> template<typename U, template<typename> class TempTemp> class
> Derived;
> template<typename V> class Derived<V, Base> : public Base<V>
> {
> public:
> template <typename W> void Fun(Derived<W, Base>&) // <-- error!?!
> {
> }
> };
> // -------------- this I added...
> int main()
> {
> Derived<int,Base> di;
> Derived<char,Base> dc;
> di.Fun(dc);
> }



Straight copy and paste from what you just posted above and it won't compile
(and my first error is the one reported by the OP).

--
John Carson


 
Reply With Quote
 
John Carson
Guest
Posts: n/a
 
      01-28-2006
"Victor Bazarov" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)
> John Carson wrote:
>>
>> Strange. It won't compile for me on either VC++ Express 2005 or a
>> Release Candidate of VS Team System.

>
> Compiled for me on Express 2005. Are you sure you used the same code?



You are using /Za aren't you? It seems that makes the difference. (It would
be nice to think that this difference is a direct result of /Za giving more
compliant behaviour. I have a suspicion, however, that it is actually a
result of /Za being less tested, so that the 2003 behaviour wasn't changed.)

--
John Carson


 
Reply With Quote
 
Victor Bazarov
Guest
Posts: n/a
 
      01-28-2006
John Carson wrote:
> "Victor Bazarov" <(E-Mail Removed)> wrote in message
> news:(E-Mail Removed)
>> John Carson wrote:
>>>
>>> Strange. It won't compile for me on either VC++ Express 2005 or a
>>> Release Candidate of VS Team System.

>>
>> Compiled for me on Express 2005. Are you sure you used the same
>> code?

>
>
> You are using /Za aren't you? It seems that makes the difference.


Yes, most certainly. If "language extensions" are disabled, I get to
check the actual compliance (and it's not bad). Since I am not usually
compiling any Windows API/SDK (which needs extensions), /Za is it.

> (It
> would be nice to think that this difference is a direct result of /Za
> giving more compliant behaviour. I have a suspicion, however, that it
> is actually a result of /Za being less tested, so that the 2003
> behaviour wasn't changed.)


I don't understand this, sorry. Perhaps further discussions on VC++
should continue in 'microsoft.public.vc.language'...

V
--
Please remove capital As from my address when replying by mail


 
Reply With Quote
 
John Carson
Guest
Posts: n/a
 
      01-28-2006
"Victor Bazarov" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)
> John Carson wrote:
>> "Victor Bazarov" <(E-Mail Removed)> wrote in message
>> news:(E-Mail Removed)
>>> John Carson wrote:
>>>>
>>>> Strange. It won't compile for me on either VC++ Express 2005 or a
>>>> Release Candidate of VS Team System.
>>>
>>> Compiled for me on Express 2005. Are you sure you used the same
>>> code?

>>
>>
>> You are using /Za aren't you? It seems that makes the difference.

>
> Yes, most certainly. If "language extensions" are disabled, I get to
> check the actual compliance (and it's not bad). Since I am not
> usually compiling any Windows API/SDK (which needs extensions), /Za
> is it.
>> (It
>> would be nice to think that this difference is a direct result of /Za
>> giving more compliant behaviour. I have a suspicion, however, that it
>> is actually a result of /Za being less tested, so that the 2003
>> behaviour wasn't changed.)

>
> I don't understand this, sorry. Perhaps further discussions on VC++
> should continue in 'microsoft.public.vc.language'...


On further investigation, I appear to be wrong. Consider this simpler case:

template<class T>
struct Base
{
Base(T arg) : t(arg)
{}
T t;
};

template<class T>
struct Derived : Base<T>
{
Derived(T arg) : Base(arg) // compilation failure here
{}
};

int main()
{
Derived<int> d(235);
}

This (correctly) fails to compile with /Za, but will compile without it.

The change needed to get it to compile with (or without) /Za is to change
the Derived constructor so that Base has a template argument:

Derived(T arg) : Base<T>(arg)
{}

For the original

Derived(T arg) : Base(arg)
{}

we get the following error message with /Za, among others:

'Derived<T>' : illegal member initialization: 'Base' is not a base or member

Thus /Za is controlling whether or not Base is interpreted as Base<T> within
Derived, which is the same issue as in the OP's code. However, I have been
unable to find any documentation of this effect of /Za.


--
John Carson


 
Reply With Quote
 
Niels Dekker - no reply address
Guest
Posts: n/a
 
      01-28-2006
Thanks, Victor and John, you really helped me out!

Victor Bazarov wrote:
> I just added this: [...]
> And compiled it successfully with VC++ v8.0.
> Please next time post the _complete_ code if you want us to be
> able to help you with any particular problem.


Sorry for not including my -empty- main() function. I hadn't realized
that this compile error only occurs when Microsoft language extensions
are enabled.

John Carson wrote:
> If you wanted to refer to the template Base inside Base, then you
> could use ::Base.


Apparently I can also use ::Base inside Derived, and this will fix my
problem! The following compiles for MSVC++ 8 (both with and without
language extensions), as well as MSVC++ 7.1 and Comeau (online). And I
guess it's still correct C++ as well!

template <typename T> class Base
{
};
template <typename U, template <typename> class TempTemp>
class Derived;

template <typename V>
class Derived<V, Base> : public Base<V>
{
public:
template <typename W> void Fun(Derived<W, ::Base>&) // <-- okay!
{
}
};

int main()
{
}


Thanks again,

Niels Dekker
www.xs4all.nl/~nd/dekkerware
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: How include a large array? Edward A. Falk C Programming 1 04-04-2013 08:07 PM
difference between pass by address and pass by reference!! blufox C Programming 2 04-03-2006 02:53 PM
Pass by reference / pass by value Jerry Java 20 09-09-2005 06:08 PM
How can we pass a template in a template function Ioannis Vranos C++ 3 03-28-2005 04:43 AM
Compiler error occurred when try to use a flexible template expression in preprocessor definesCompiler error occurred when try to use a flexible template expression in preprocessor defines snnn C++ 6 03-14-2005 04:09 PM



Advertisments