Thread: left operand must be l-value

  1. #1
    Registered User
    Join Date
    Jul 2005
    Posts
    64

    left operand must be l-value

    Hello,

    I am having trouble with the error message in the title: "Left operand must be l-value." I created a template class as follows:

    Code:
    template <class T>
    class vector
    {
    	T *ptr;
    	int size;
    	vector(const int&);
    public:
    	vector();
    	vector(const vector&);
    	vector operator =(const vector&);
    	void operator >>(const T&);
    	int mag();
    	T operator()(const int&) const;
    	//void operator <<(const T&);		//add this later, just to be fancy
    	~vector();
    	friend ostream& operator <<(ostream&, vector&);
    };
    
    template <class T>
    vector<T>::vector()
    {
    	size = 0;
    	ptr = NULL;
    }
    
    template <class T>
    vector<T>::vector(const vector &another)
    {
    	size = another.size;
    	ptr = new T [size];
    	for (int i=0; i<size; i++)
    	{
    		ptr[i] = another.ptr[i];
    	}
    }
    
    template <class T>
    vector<T>::vector(const int &a)
    {
    	size = a;
    	ptr = new T [a];
    }
    
    template <class T>
    void vector<T>::operator >>(const T &addition)
    {
    	vector<T> temp(size+1);
    	for (int i=0; i<size; i++)
    	{
    		temp.ptr[i] = ptr[i];
    	}
    	temp.ptr[size] = addition;
    	delete [] ptr;
    	size = temp.size;
    	ptr = new T [size];
    	for (i=0; i<size; i++)
    	{
    		ptr[i] = temp.ptr[i];
    	}
    	return;
    }
    
    template <class T>
    T vector<T>::operator()(const int &a) const
    {
    	return ptr[a];
    }
    
    template <class T>
    int vector<T>::mag()
    {
    	return size;
    }
    
    template <class T>
    vector<T> vector<T>::operator =(const vector &another)
    {
    	vector temp(another.size);
    	temp.ptr = new T [size];
    	for (int i=0; i<temp.size; i++)
    	{
    		temp.ptr[i] = another.ptr[i];
    	}
    	return temp;
    }
    
    template <class T>
    vector<T>::~vector()
    {
    	delete [] ptr;
    }
    After doing this, I created a regular struct:

    Code:
    struct BGT
    {
    bool DC;
    };
    You don't have to go through all the code if you don't want to. I just included it for convenience. The problem arises when I use the () operator to set the DC value. I can tell you that the vector overloaded operator works fine. But when I do something like this:

    Code:
    vector<BGT> bgt;
    /*
    ...
    after increasing the size of the vector
    ...
    */
    bgt(index).DC = true;        //THIS is where I get the error
    I just can't understand why. Can anyone please help?

    Many, MANY thanks in advance.

    Bill
    Last edited by Bill83; 10-10-2006 at 11:41 AM.

  2. #2
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    Quote Originally Posted by Bill83
    Hello,

    I am having trouble with the error message in the title: "Left operand must be l-value." I created a template class as follows:
    [...]
    After doing this, I created a regular struct:

    Code:
    struct BGT
    {
    bool DC;
    }
    [...] The problem arises when I use the () operator to set the DC value. I can tell you that the vector overloaded operator works fine. But when I do something like this:

    Code:
    vector<BGT> bgt;
    /*
    ...
    after increasing the size of the vector
    ...
    */
    bgt(index).DC = true;        //THIS is where I get the error
    And you should be getting that error. bgt doesn't even have a vector as a data member so operator() is completely out of context. Even if you put a vector in the struct it might not work, because of how operators chain together. operator() returns T. Can you guarantee that T is a struct or a class that has DC for a member?

  3. #3
    Registered User
    Join Date
    Jul 2005
    Posts
    64
    This is actually the first time I ever programmed with templates, so obviously I didn't get the whole picture. I think I'll just get rid of the vector class altogether and just create a dynamic array.

  4. #4
    Registered User
    Join Date
    Jul 2005
    Posts
    64
    But just out of curiosity, how do I include vector as a data member if I don't have anywhere to use it in the class definitions?

  5. #5
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    You don't have to scrap the whole idea. Get your vector to work completely with one type, say int, and then make it a template. It is a lot simpler than going the other way because if you design a template you (kind of) have to keep in mind anything it could ever be used for. Getting it to work perfectly with one type pretty much guarantees that it will work with other types.

  6. #6
    Registered User
    Join Date
    Mar 2006
    Posts
    725
    You should also get comfortable with working with size_t instead of int, as that's the more conventional type for specifying sizes and indices.
    Code:
    #include <stdio.h>
    
    void J(char*a){int f,i=0,c='1';for(;a[i]!='0';++i)if(i==81){
    puts(a);return;}for(;c<='9';++c){for(f=0;f<9;++f)if(a[i-i%27+i%9
    /3*3+f/3*9+f%3]==c||a[i%9+f*9]==c||a[i-i%9+f]==c)goto e;a[i]=c;J(a);a[i]
    ='0';e:;}}int main(int c,char**v){int t=0;if(c>1){for(;v[1][
    t];++t);if(t==81){J(v[1]);return 0;}}puts("sudoku [0-9]{81}");return 1;}

  7. #7
    Registered User
    Join Date
    Jul 2005
    Posts
    64
    Thank you guys for all your help. Unfortunately I still don't understand why it is not working. I did start out as programming a vector class for double, then I changed it to a template. In the operator (), I thought the whole point was to return type T (BGT) so that in the end I could access the DC data member (bgt(index)).DC
    Last edited by Bill83; 10-10-2006 at 11:42 AM.

  8. #8
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    Like I said though, you should work on getting your vector to work with one type. Also, bgt(index).DC will only work if you support operator chaining, which your program, in its current form, does not.

    I made a stripped down vector class for you to analyse. Now there is a LOT missing from this implementation, so don't steal it, but notice how my operators return references. That is what allows operator chaining to work.
    Code:
    #include <iostream>
    #include <cstdlib>
    
    class vector {
       public:
       vector(size_t num, const int &val);
       ~vector();
    
       // http://www.parashift.com/c++-faq-lit...html#faq-18.12
       const int &operator[] (const size_t place) const;
       int &operator[] (const size_t place);
       
       private:
       int *data;
       int *back;
       size_t size;
    };
    
    vector::vector(size_t num, const int &val)
    {
       data = new int[num];
       if(data == NULL)
       {
          std::cerr << "memory exhausted\n";
          std::exit(EXIT_FAILURE); // Not a cool way to handle it.
       }
       size = num;
       while ( num-- )
         data[num] = val;
       back = &data[size];
    }
    
    vector::~vector()
    {
       delete[] data;
       data = NULL;
    }
    
    const int &vector::operator[] (const size_t place) const
    {
       return data[place];
    }
    
    int &vector::operator[] (const size_t place)
    {
       return data[place];
    }
    
    int main()
    {
       vector v(5, 10); // five items with the number ten
       std::cout << "For example, get item one: " << v[1] << "\n";
       return EXIT_SUCCESS;
    }
    Also, while you are free to use operator() differently, I've only seen it most commonly used to create functors. If you want to avoid some [slight] confusion, you might want to overload the subscript operator instead.
    Last edited by whiteflags; 10-10-2006 at 01:06 PM.

  9. #9
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Isn't EXIT_SUCCESS in the std namespace?
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  10. #10
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    No, EXIT_SUCCESS is a macro.

  11. #11
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Well, I mean, shouldn't you need to use std::EXIT_SUCCESS? I know it's a macro.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  12. #12
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    How can a macro be in a namespace? No, it compiles and works just fine.

  13. #13
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Oh, *slaps head* it's a macro. I knew that.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  14. #14
    Registered User
    Join Date
    Mar 2006
    Posts
    725
    What does "mag"() stand for? Does it return a "magnum"? A "magnifier"? A "magnitude"? And I'm no expert, but you just might want to include a little add/remove item functionality.
    Code:
    #include <stdio.h>
    
    void J(char*a){int f,i=0,c='1';for(;a[i]!='0';++i)if(i==81){
    puts(a);return;}for(;c<='9';++c){for(f=0;f<9;++f)if(a[i-i%27+i%9
    /3*3+f/3*9+f%3]==c||a[i%9+f*9]==c||a[i-i%9+f]==c)goto e;a[i]=c;J(a);a[i]
    ='0';e:;}}int main(int c,char**v){int t=0;if(c>1){for(;v[1][
    t];++t);if(t==81){J(v[1]);return 0;}}puts("sudoku [0-9]{81}");return 1;}

  15. #15
    Registered User
    Join Date
    Jul 2005
    Posts
    64
    Thank you citizen (and the rest of you). You have all been a great help.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Odd 3D Invis Objects?
    By Zeusbwr in forum Game Programming
    Replies: 4
    Last Post: 12-07-2004, 07:01 PM
  2. Binary Search Trees Part III
    By Prelude in forum A Brief History of Cprogramming.com
    Replies: 16
    Last Post: 10-02-2004, 03:00 PM
  3. pointer to array of objects of struct
    By undisputed007 in forum C++ Programming
    Replies: 12
    Last Post: 03-02-2004, 04:49 AM
  4. Request for comments
    By Prelude in forum A Brief History of Cprogramming.com
    Replies: 15
    Last Post: 01-02-2004, 10:33 AM
  5. Please help me
    By teedee46 in forum C++ Programming
    Replies: 9
    Last Post: 05-06-2002, 11:28 PM