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

Discussion in 'C++' started by Niels Dekker - no reply address, Jan 27, 2006.

  1. 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
     
    Niels Dekker - no reply address, Jan 27, 2006
    #1
    1. Advertising

  2. 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
     
    Victor Bazarov, Jan 28, 2006
    #2
    1. Advertising

  3. Niels Dekker - no reply address

    John Carson Guest

    "Victor Bazarov" <> wrote in message
    news:
    > 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
     
    John Carson, Jan 28, 2006
    #3
  4. Niels Dekker - no reply address

    John Carson Guest

    "Niels Dekker - no reply address" <> wrote in
    message news:
    > 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
     
    John Carson, Jan 28, 2006
    #4
  5. John Carson wrote:
    > "Victor Bazarov" <> wrote in message
    > news:
    >> 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
     
    Victor Bazarov, Jan 28, 2006
    #5
  6. Niels Dekker - no reply address

    John Carson Guest

    "Victor Bazarov" <> wrote in message
    news:
    > 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
     
    John Carson, Jan 28, 2006
    #6
  7. Niels Dekker - no reply address

    John Carson Guest

    "Victor Bazarov" <> wrote in message
    news:
    > 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
     
    John Carson, Jan 28, 2006
    #7
  8. John Carson wrote:
    > "Victor Bazarov" <> wrote in message
    > news:
    >> 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
     
    Victor Bazarov, Jan 28, 2006
    #8
  9. Niels Dekker - no reply address

    John Carson Guest

    "Victor Bazarov" <> wrote in message
    news:
    > John Carson wrote:
    >> "Victor Bazarov" <> wrote in message
    >> news:
    >>> 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
     
    John Carson, Jan 28, 2006
    #9
  10. 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
     
    Niels Dekker - no reply address, Jan 28, 2006
    #10
  11. Niels Dekker - no reply address

    John Carson Guest

    "Niels Dekker - no reply address" <> wrote in
    message news:
    > 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
     
    John Carson, Jan 28, 2006
    #11
  12. 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
     
    Niels Dekker - no reply address, Jan 28, 2006
    #12
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Pierre-Marc Fournier

    Template code works with g++ but not MSVC++

    Pierre-Marc Fournier, Jul 13, 2004, in forum: C++
    Replies:
    6
    Views:
    470
    Alf P. Steinbach
    Jul 13, 2004
  2. Thomas Casanova

    template from MSVC++ to Linux gcc 3.3.4

    Thomas Casanova, Nov 9, 2004, in forum: C++
    Replies:
    3
    Views:
    463
    Andre Dajd
    Nov 9, 2004
  3. Ben Kial
    Replies:
    1
    Views:
    676
    Eric Enright
    Nov 15, 2004
  4. nw
    Replies:
    0
    Views:
    331
  5. nguillot
    Replies:
    5
    Views:
    539
Loading...

Share This Page