Simple template experiment fails

Discussion in 'C++' started by Bert Aerts (rm X), Sep 14, 2009.

  1. With following files, the print statement
    cout << amt.getElem(2) << endl;
    can not be compiled.

    Though getElem returns Type, in this case class MyType, which has print
    functions defined.

    It does work for int and long double types...

    What am I missing? Thanks for any help!

    /*
    * chapter11.h
    *
    * Created on: Sep 13, 2009
    * Author: bert
    */

    #ifndef CHAPTER11_H_
    #define CHAPTER11_H_

    // template defining an array
    template <class Type>
    class Array
    {
    public:
    Array();
    ~Array();
    void setSize(size_t value);
    size_t getSize();
    void setElem(size_t index, Type value);
    Type getElem(size_t index);
    private:
    Type *elems;
    size_t numElems;
    };

    // a user-defined type
    class MyType
    {
    public:
    MyType();
    // a member function that modifies instances of MyType
    void sanitize();
    void print(ostream *os);
    private:
    int value;
    };

    #endif /* CHAPTER11_H_ */


    /*
    * chapter11.cpp
    *
    * Created on: Sep 13, 2009
    * Author: bert
    */

    #include <iostream>
    using namespace std;

    #include <stdlib.h> // to get exit()
    #include "chapter11.h"

    #define SIZE 10

    template<class Type>
    Array<Type>::Array()
    {
    elems = 0;
    numElems = 0;
    }

    template<class Type>
    Array<Type>::~Array()
    {
    if( elems != 0 )
    {
    cout << "delete[] " << (void *) elems << endl;
    delete[] elems;
    }
    }

    template<class Type>
    void Array<Type>::setSize(size_t value)
    {
    if( elems != 0 ) delete[] elems;
    numElems = value;
    elems = new Type[value];
    if( elems != 0 )
    {
    cout << "elems pointer is " << (void *)elems << endl;
    }
    else
    {
    cout << "new[] failed" << endl;
    exit(1);
    }
    }

    template<class Type>
    size_t Array<Type>::getSize()
    {
    return numElems;
    }

    template<class Type>
    void Array<Type>::setElem(size_t index, Type value)
    {
    if( index < numElems )
    {
    elems[index] = value;
    }
    else
    {
    cout << "setElem bad index " << index << " >= " << numElems << endl;
    exit(1);
    }
    }

    template<class Type>
    Type Array<Type>::getElem(size_t index)
    {
    if( index >= numElems )
    {
    cout << "getElem bad index " << index << " >= " << numElems << endl;
    exit(1);
    }
    else
    {
    return elems[index];
    }
    }

    void MyType::print(ostream *os)
    {
    *os << "MyType{" << value << '}';
    }

    MyType::MyType()
    {
    value = 0;
    }

    void MyType::sanitize()
    {
    value = 22;
    }

    ostream &operator<<(ostream &os, MyType &theMyType)
    {
    theMyType.print(&os);
    return os;
    }

    int main()
    {
    Array<int> ai;
    Array<long double> ald;
    Array<MyType> amt;
    MyType refmt;

    ai.setSize(SIZE);
    ai.setElem(2,5);
    cout << "ai[2] = " << ai.getElem(2) << endl;

    ald.setSize(SIZE);
    ald.setElem(2,3.1415);
    cout << "ald[2] = " << ald.getElem(2) << endl;

    amt.setSize(SIZE);
    cout << "refmt is " << refmt << endl;
    amt.setElem(2,refmt);
    cout << amt.getElem(2) << endl; // DOES NOT COMPILE
    refmt.sanitize();
    cout << "refmt.sanitize gives " << refmt << endl;
    }
     
    Bert Aerts (rm X), Sep 14, 2009
    #1
    1. Advertising

  2. Bert Aerts (rm X) wrote:
    > With following files, the print statement
    > cout << amt.getElem(2) << endl;
    > can not be compiled.
    >
    > Though getElem returns Type, in this case class MyType, which has print
    > functions defined.
    >
    > It does work for int and long double types...
    >
    > What am I missing? Thanks for any help!
    >
    > [..]
    > template<class Type>
    > Type Array<Type>::getElem(size_t index)

    ^^^^
    Returns by value, yes?

    > {

    [..]
    > }
    >
    > [..]
    > ostream &operator<<(ostream &os, MyType &theMyType)

    ^^^^^^^^^^
    The argument is a reference to non-const, yes?

    > {
    > theMyType.print(&os);
    > return os;
    > }
    >
    > int main()
    > {
    > [..]
    > cout << amt.getElem(2) << endl; // DOES NOT COMPILE


    'amt.getElem(2)' returns a temporary, which cannot be bound to a
    reference to non-const.

    I didn't check what the compiler says, you ought to post the actual
    compiler message (do, next time).

    > refmt.sanitize();
    > cout << "refmt.sanitize gives " << refmt << endl;
    > }


    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Sep 14, 2009
    #2
    1. Advertising

  3. Victor Bazarov wrote:
    > Bert Aerts (rm X) wrote:
    >> With following files, the print statement
    >> cout << amt.getElem(2) << endl;
    >> can not be compiled.
    >>
    >> Though getElem returns Type, in this case class MyType, which has
    >> print functions defined.
    >>
    >> It does work for int and long double types...
    >>
    >> What am I missing? Thanks for any help!
    >>
    >> [..]
    >> template<class Type>
    >> Type Array<Type>::getElem(size_t index)

    > ^^^^
    > Returns by value, yes?
    >
    >> {

    > [..]
    >> }
    >>
    >> [..]
    >> ostream &operator<<(ostream &os, MyType &theMyType)

    > ^^^^^^^^^^
    > The argument is a reference to non-const, yes?
    >
    >> {
    >> theMyType.print(&os);
    >> return os;
    >> }
    >>
    >> int main()
    >> {
    > > [..]
    >> cout << amt.getElem(2) << endl; // DOES NOT COMPILE

    >
    > 'amt.getElem(2)' returns a temporary, which cannot be bound to a
    > reference to non-const.
    >
    > I didn't check what the compiler says, you ought to post the actual
    > compiler message (do, next time).
    >


    The GNU g++ compiler says:
    .../chapter11.cpp:123: error: no match for ‘operator<<’ in ‘std::cout <<
    amt.Array<Type>::getElem [with Type = MyType](2ul)’

    >> refmt.sanitize();
    >> cout << "refmt.sanitize gives " << refmt << endl;
    >> }

    >
    > V


    I solved the issue by following lines
    in chapter11.h
    Type &getElem(size_t index);
    and in chapter11.cpp
    template<class Type>
    Type &Array<Type>::getElem(size_t index)

    returning a reference iso by value.
    Now the print works.

    Thanks for your reply.
     
    Bert Aerts (rm X), Sep 15, 2009
    #3
  4. Bert Aerts (rm X) wrote:
    > Victor Bazarov wrote:
    >> Bert Aerts (rm X) wrote:
    >>> With following files, the print statement
    >>> cout << amt.getElem(2) << endl;
    >>> can not be compiled.
    >>>
    >>> Though getElem returns Type, in this case class MyType, which has
    >>> print functions defined.
    >>>
    >>> It does work for int and long double types...
    >>>
    >>> What am I missing? Thanks for any help!
    >>>
    >>> [..]
    >>> template<class Type>
    >>> Type Array<Type>::getElem(size_t index)

    >> ^^^^
    >> Returns by value, yes?
    >>
    >>> {

    >> [..]
    >>> }
    >>>
    >>> [..]
    >>> ostream &operator<<(ostream &os, MyType &theMyType)

    >> ^^^^^^^^^^
    >> The argument is a reference to non-const, yes?
    >>
    >>> {
    >>> theMyType.print(&os);
    >>> return os;
    >>> }
    >>>
    >>> int main()
    >>> {
    >> > [..]
    >>> cout << amt.getElem(2) << endl; // DOES NOT COMPILE

    >>
    >> 'amt.getElem(2)' returns a temporary, which cannot be bound to a
    >> reference to non-const.
    >>
    >> I didn't check what the compiler says, you ought to post the actual
    >> compiler message (do, next time).
    >>

    >
    > The GNU g++ compiler says:
    > ../chapter11.cpp:123: error: no match for ‘operator<<’ in ‘std::cout <<
    > amt.Array<Type>::getElem [with Type = MyType](2ul)’
    >
    >>> refmt.sanitize();
    >>> cout << "refmt.sanitize gives " << refmt << endl;
    >>> }

    >>
    >> V

    >
    > I solved the issue by following lines
    > in chapter11.h
    > Type &getElem(size_t index);
    > and in chapter11.cpp
    > template<class Type>
    > Type &Array<Type>::getElem(size_t index)
    >
    > returning a reference iso by value.
    > Now the print works.


    Or, you could have solved it by making 'print' a const member and making
    operator<< accept a reference to const as its second argument. Read up
    on "const correctness".

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Sep 16, 2009
    #4
    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. CrazyCube
    Replies:
    1
    Views:
    379
    Kevin Spencer
    Oct 22, 2004
  2. Peter

    design experiment?

    Peter, Feb 22, 2005, in forum: Java
    Replies:
    4
    Views:
    350
    Chris Uppal
    Feb 23, 2005
  3. Richard
    Replies:
    17
    Views:
    602
    The Farkinator
    Oct 15, 2003
  4. Rob Collyer

    Please help this google experiment.

    Rob Collyer, Sep 25, 2004, in forum: HTML
    Replies:
    3
    Views:
    297
  5. Johannes Schaub (litb)

    Experiment with unnamed namespace and template

    Johannes Schaub (litb), Oct 13, 2010, in forum: C++
    Replies:
    4
    Views:
    507
    Victor Bazarov
    Oct 13, 2010
Loading...

Share This Page