By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,156 Members | 989 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,156 IT Pros & Developers. It's quick & easy.

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

P: n/a
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
Jan 27 '06 #1
Share this Question
Share on Google+
11 Replies


P: n/a
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
Jan 28 '06 #2

P: n/a
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:EZ********************@comcast.com
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
Jan 28 '06 #3

P: n/a
"Niels Dekker - no reply address" <un*****@this.is.invalid> wrote in
message news:43***************@this.is.invalid
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
Jan 28 '06 #4

P: n/a
John Carson wrote:
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:EZ********************@comcast.com
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
Jan 28 '06 #5

P: n/a
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:7q******************************@comcast.com
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
Jan 28 '06 #6

P: n/a
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:7q******************************@comcast.com
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
Jan 28 '06 #7

P: n/a
John Carson wrote:
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:7q******************************@comcast.com
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
Jan 28 '06 #8

P: n/a
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:i5******************************@comcast.com
John Carson wrote:
"Victor Bazarov" <v.********@comAcast.net> wrote in message
news:7q******************************@comcast.com
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
Jan 28 '06 #9

P: n/a
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
Jan 28 '06 #10

P: n/a
"Niels Dekker - no reply address" <un*****@this.is.invalid> wrote in
message news:43***************@this.is.invalid
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!

I know. I said that in my post.

--
John Carson
Jan 28 '06 #11

P: n/a
John Carson wrote:
Niels Dekker wrote:
Apparently I can also use ::Base inside Derived, and this will fix my
problem!


I know. I said that in my post.


You're right :-)

Kind regards,

Niels Dekker
Jan 28 '06 #12

This discussion thread is closed

Replies have been disabled for this discussion.