Template code look okay, compilers disagrees

Template code look okay, compilers disagrees

Post by Gerben Venekam » Mon, 28 Jul 2003 19:31:03



Hello,

It seems I'm having some trouble regarding templates. Let me describe what
I'm trying to accomplish first before I show you the code.

I'm anticipating that I'll be needing several versions of a paricular class.
It is only at run-time that I know which version is the one. Thus, I would
like to use the Factory pattern to solve this problem. To complicate things
a bit, I'll need to pass on a templated class, in fact it's a derived class
from basic_streambuf<>. The Factory class remembers the buffer and when it
instanciates a particular class, that class's constructor needs that buffer
as a parameter. This fact is not shown in the code shown here to keep it as
minimal as possible. In the example code I'm using class names Version
(base class) and Version_V1 (derived class) to illustrate the concept of
diffrent versions.

This is the code I would like to compile:

template<typename _CharT>
class Version
{
public:
   Version() { }
   virtual ~Version() { }

Quote:};

template<typename _CharT>
class Version_V1 : public Version<_CharT>
{
public:
   Version_V1() : Version<_CharT>() { }
   ~Version_V1() { }

Quote:};

template<typename _CharT>
class Factory
{
public:
   Factory() { }
   ~Factory() { }

   template<typename T>
   Version<T>* Create(void)
   {
     return new Version_V1<T>();
   }

Quote:};

template<typename _CharT>
void
DoIt(void)
{
   Factory<_CharT>* f = new Factory<_CharT>();
   Version<_CharT>* v1 = f->Create<_CharT>();    // error: parse error before
`>' token

Quote:}

int main(int argc, char* argv[])
{
   DoIt<char>();

Quote:}

Without using templates this works fine. Even templating the Version,
Version_V1 and Factory classes works fine.

It seems that the problem is with the DoIt() function. When I do not
template this function, thus substituting <_CharT> by e.g. <int>, all is
well. However templating this function results in the following error:
   templ_2.C:36: error: parse error before `>' token

Can any one explain to me what it is that I'm doing wrong?

Thanks in advance,
Gerben

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

 
 
 

Template code look okay, compilers disagrees

Post by llewell » Tue, 29 Jul 2003 01:28:34



Quote:> Hello,

> It seems I'm having some trouble regarding templates. Let me describe what
> I'm trying to accomplish first before I show you the code.

> I'm anticipating that I'll be needing several versions of a paricular class.
> It is only at run-time that I know which version is the one. Thus, I would
> like to use the Factory pattern to solve this problem. To complicate things
> a bit, I'll need to pass on a templated class, in fact it's a derived class
> from basic_streambuf<>. The Factory class remembers the buffer and when it
> instanciates a particular class, that class's constructor needs that buffer
> as a parameter. This fact is not shown in the code shown here to keep it as
> minimal as possible. In the example code I'm using class names Version
> (base class) and Version_V1 (derived class) to illustrate the concept of
> diffrent versions.

> This is the code I would like to compile:

> template<typename _CharT>

Names which begin with an underscore followed by an uppercase letter
    are reserved to the implementation.

- Show quoted text -

Quote:> class Version
> {
> public:
>    Version() { }
>    virtual ~Version() { }
> };

> template<typename _CharT>
> class Version_V1 : public Version<_CharT>
> {
> public:
>    Version_V1() : Version<_CharT>() { }
>    ~Version_V1() { }
> };

> template<typename _CharT>
> class Factory
> {
> public:
>    Factory() { }
>    ~Factory() { }

>    template<typename T>
>    Version<T>* Create(void)
>    {
>      return new Version_V1<T>();
>    }
> };

> template<typename _CharT>
> void
> DoIt(void)
> {
>    Factory<_CharT>* f = new Factory<_CharT>();
>    Version<_CharT>* v1 = f->Create<_CharT>();    // error: parse
> error before

   Version<_CharT>* v1 = f->template Create<_CharT>();

'template' is required to inform the compiler that 'Create' is a
    template-id, and therefor that <> should be parsed as enclosing
    template parameters, and not as operator< and operator> .

Quote:> `>' token
> }

> int main(int argc, char* argv[])
> {
>    DoIt<char>();
> }

[snip]

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

 
 
 

Template code look okay, compilers disagrees

Post by Richard Smit » Wed, 30 Jul 2003 06:32:07



> template<typename _CharT>

A leading underscore followed by either another underscore
or an uppercase letter is reserved.  You should choose
another naming convention for template parameters.

Quote:> template<typename _CharT>
> class Factory

I assume you have a reason for templating this on _CharT?
The code given makes no use of the template parameter.
Naively, I would expect either the Factory class or the
Create method to be templated, but not both.

Quote:> template<typename _CharT>
> void
> DoIt(void)
> {
>    Factory<_CharT>* f = new Factory<_CharT>();
>    Version<_CharT>* v1 = f->Create<_CharT>();    // error: parse error before
> `>' token

Unfortunately, this is one of those subtleties you get with
complicated templates (e.g. using member templates of class
templates).  To fix it you should write

  f->template Create<_CharT>()

This tells the compiler that Create is a member template, so
that it knows to parse the "<" a the start of a list of
template arguments rather than as a less-than operator.
This in turn allows the compiler to do better error
checking.  For more details on this, I'd suggest investing
in a copy of Vandevoorde and Josuttis' excellent book on
templates, "C++ Templates: The Complete Guide". Section
9.3.3 deals with this particular issue.

--
Richard Smith

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

 
 
 

1. Binding reference to rvalue - compilers disagree

Hello All:

Consider the following code:

template<typename T> struct D : T {};

struct A {
    A();    
    A(A&);
    A(D<A>&);
    operator D<A>&();

int f(const A &);
int x = f(A());  // (*) EDG 3.0 - "A::A(A &)", required for copy that
was eliminated, is not callable because reference parameter cannot be
bound to rvalue.

VC7.1, GCC 3.2 and BCC 5.5 accepted (*).
After reading 8.5/14/4/2, 8.5.3/5/2/1 and core issue #291 it seems to
me that (*) is legal semantically construct the temporary, from the
rvalue, using A(D<A>&) and bind it to the reference.

Can anyone tell whether the above code is legal?

Thanks,
Rani

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]

[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]

2. ext modem with Palm V?

3. koenig lookup question - compilers disagree

4. Is there a way??? HMS1050/HAI OmniLT Ques.

5. Compilers disagree about assigment of lvalue?

6. Shadow folder files

7. Problem with overloaded function templates (EDG and g++ disagree)

8. What is the difference between CE, P/PC and Pocket PC

9. Looking for simple PC "okay-dokay" program.

10. how to see template code generated by compiler?

11. looking for template based code generation tool

12. Workarounds for broken compilers (template template params)

13. Possible workaround for template template parameters on older compilers?