CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 13 of 13

Thread: boost Variant

  1. #1
    Join Date
    Jun 2012
    Posts
    127

    boost Variant

    Compiler told me that it cannot find copy constructor but I declared and implemented it for both class Lin and Point... What I did wrong...
    Many thanks in advance !


    1>------ Build started: Project: Exercise 3 Variant, Configuration: Debug Win32 ------
    1> main.cpp
    1>c:\program files\boost\boost_1_47\boost\variant\detail\initializer.hpp(95): error C2558: class 'Line' : no copy constructor available or copy constructor is declared 'explicit'
    1> c:\program files\boost\boost_1_47\boost\variant\detail\initializer.hpp(90) : while compiling class template member function 'int boost:etail::variant::make_initializer_node::apply<BaseIndexPair,Iterator>::initializer_node::initialize(void *,const Line &)'
    1> with
    1> [
    1> BaseIndexPair=boost::mpl:air<boost:etail::variant::make_initializer_node::apply<boost::mpl:air<boost:etail::variant::initializer_root,boost::mpl::int_<0>>,boost::mpl::l_iter<boost::mpl::list2<Point,Line>>>::initializer_node,boost::mpl::int_<1>>,
    1> Iterator=boost::mpl::l_iter<boost::mpl::list1<Line>>
    1> ]
    1> c:\program files\boost\boost_1_47\boost\variant\variant.hpp(1208) : see reference to class template instantiation 'boost:etail::variant::make_initializer_node::apply<BaseIndexPair,Iterator>::initializer_node' being compiled
    1> with
    1> [
    1> BaseIndexPair=boost::mpl:air<boost:etail::variant::make_initializer_node::apply<boost::mpl:air<boost:etail::variant::initializer_root,boost::mpl::int_<0>>,boost::mpl::l_iter<boost::mpl::list2<Point,Line>>>::initializer_node,boost::mpl::int_<1>>,
    1> Iterator=boost::mpl::l_iter<boost::mpl::list1<Line>>
    1> ]
    1> c:\program files\boost\boost_1_47\boost\variant\variant.hpp(1327) : see reference to class template instantiation 'boost::variant<T0_,T1>::initializer' being compiled
    1> with
    1> [
    1> T0_=Point,
    1> T1=Line
    1> ]
    1> c:\program files\boost\boost_1_47\boost\variant\variant.hpp(1399) : see reference to function template instantiation 'void boost::variant<T0_,T1>::convert_construct<const T>(T &,int,boost::mpl::false_)' being compiled
    1> with
    1> [
    1> T0_=Point,
    1> T1=Line,
    1> T=Point
    1> ]
    1> c:\all my\с++\ha level 8\solution\level 8\exercise 3 variant\main.cpp(28) : see reference to function template instantiation 'boost::variant<T0_,T1>::variant<Point>(const T &)' being compiled
    1> with
    1> [
    1> T0_=Point,
    1> T1=Line,
    1> T=Point
    1> ]
    ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========


    Code:
    //line.h
    #ifndef LINE_H
    #define LINE_H
    #include "Shape.h"
    #include "Point.h"
    #include <string>
    #include <iostream>
    using namespace std;
    class Line : public Shape
    {
    	 private:
          Point start; 
          string discrib;
    	  Point end;
    
       public:
          //constructors and destructor
          Line();
          Line(string x, Point P_start, Point P_end);
    	  Line(Line& line); // line copy constructor
          ~Line();
    		
          //getters and setters
          void SetStart ( Point SomePoint);
          void SetEnd ( Point SomePoint);
          Point GetStart() ;
          Point GetEnd() ;
    
    	  Line operator = ( Line& l);
    	 // friend ostream& operator << (ostream& os , const Line& l);
    
    	  //other useful methods
          void ToString(); 
    };
    
    #endif
    
    //point.h
    #ifndef POINT_H 
    #define POINT_H
    #include "Shape.h"
    #include <iostream>
    #include <string>
    using namespace std;
    class Point : public Shape
    
    {
    	private:
    double Xcoord;
    double Ycoord;
    
    	public:
    Point();
    Point (double xNew, double yNew);
    Point( Point& point); // copy constructor for Point
    ~Point();
          
    void X( double Value);
    void Y( double Value);
    double X() ;
    double Y() ;
    
    Point operator = ( Point& p);
    friend ostream& operator << (ostream& os ,  Point& p);
    void ToString();
    
    };
    
    #endif 
    
    // shape.h 
    #ifndef Shape_h 
    #define Shape_h
    #include <iostream>
    #include "stdlib.h"
    #include "Shape.h"
    using namespace std; 
    class Shape
    {
    	protected: 
    int m_id;  // Add a data member for an id number of type int.
    	public: 
    int id; 
    int ID(); // return n_id data
    Shape(); // initialises the id using a random number
    Shape(const Shape &OtherShape); // copies the id member
    Shape operator = (const Shape &OtherShape); // copies the id member
    virtual void ToString() ; // returns the id as string e.g. “ID: 123”
    };
    #endif 
    
    //line.cpp
    #include <iostream>
    //#include <math.h>
    #include "line.h"
    #include "Point.h"
    #include "Shape.h"
    #include <string>
    using namespace std;
    
    Line::Line(){}
    
    Line::Line(string x, Point P_start, Point P_end)
    	:discrib(x), start(P_start), end(P_end) {}
    
    Line::Line( Line& line)
    {
    	start = line.start;
    	end = line.end;
    }
    
    Line::~Line() {}
    
    void Line::SetStart( Point SomePoint)
    	{
       start = SomePoint;
    	}
    
    void Line::SetEnd ( Point SomePoint)
    	{
      end = SomePoint;
    	}
    
    Point Line::GetStart() 
    	{
       return start;
    	}
    
    Point Line::GetEnd() 
    	{
       return end;
    	}
    
    Line Line::operator = ( Line& l)
    	 {
    	if (this == &l)
    	{
    		return * this; 
    	}
    	/*member function from base class */
    	m_id = l.m_id;
    	/* data from derived class*/
    	discrib = l.discrib;
    	start = l.start;
    	end = l.end;
    	return *this ;
    	} 
    
    
    
    void Line::ToString()  // returns the line as string              
    	{
    	cout << "[[" << discrib << "," 
    		 << start << "," << end << "]]" << endl;
    	}
    
    
    //Point.cpp
    #include <iostream>
    #include "Point.h"
    using namespace std;
    
    Point::Point() {}
    
     Point::Point (double xNew, double yNew)
    	 : Xcoord(xNew), Ycoord(yNew) {}
    
    Point::~Point() {} //Destructor
    
    Point::Point( Point& point) // Point copy constructor
    {
        Xcoord = point.Xcoord;
        Ycoord = point.Ycoord;
    }
    
    
    void Point::X( double Value) 
    {//Assign X-coordinate the Value that is put into the main
        Xcoord = Value; 
    }
    
    void Point::Y( double Value) 
    {//Assing Y-coordinate the Value that is put into the main
        Ycoord = Value;
    }
    
    double Point::X()  
    {
    return Xcoord;//Return X-coordinate
    }
    
    double Point::Y()  
    {
    return Ycoord;//Return Y-coordinate
    }
    
    
    void Point::ToString()
    	{
    cout << "( " << X() << "," 
         << Y() << " )";
    	}
    
    Point Point::operator = ( Point& p)
    {
    	if (this == &p)
    	{
    		return * this; 
    	}	
    
    m_id = p.m_id;// member function from base class 	
    Xcoord = p.Xcoord;// data from derived class
    Ycoord = p.Ycoord;
    return *this; 
    } 
    ostream& operator << (ostream& os ,  Point& p)
    	{
    		os << "[" << p.X() << "," << p.Y() << "]";
    		return os ; 
    	}
    
    
    
    //Shape.cpp 
    #include <iostream>
    #include "Shape.h"
    using namespace std; 
    
    
    Shape::Shape() // initialises the id using a random number
    	
    	{
    	m_id = rand();
    	///cout << "id of shape is: " << m_id << endl; 
    	}
    
    int Shape::ID() // retrieve the id of the shape
    	{
    	return m_id; 
    	}
    	
    void Shape::ToString() // returns the id as string              
    {
    	// cout << "ID: "<< ID(); 
    }
    
    Shape::Shape(const Shape &OtherShape)
    	{//copy constructor that copies the id member
    		id = OtherShape.m_id;
    	}
    	
    Shape Shape::operator = (const Shape& OtherShape)
    	{//assignment operator that copies the id member
    	
    	if (this == &OtherShape)
    		{
    			return *this;
    		}
    	m_id = OtherShape.m_id;
    	return *this; 
    	}
    
    
    
    //main.cpp
    //Variant
    
    #include "Point.h"//header file declaration of class Point
    #include "Line.h"//header file declaration of class Line
    //#include "Circle.h"//header file declaration of class Circle
    #include "Shape.h"//header file declaration of class Shape
    #include <boost/variant.hpp>//includes boost class for variant
    #include <iostream>// C++ style I/O using operator overloading
    #include <ostream>
    using namespace std;// The C++ logical collection of functions
     
     
    //defines a shape type that can be of the form Point, Line or Circle
    typedef boost::variant<Point, Line/*, Circle*/> ShapeType;
     
    //function that returns a variant with the specified shape
     
    ShapeType shape_type(){
    int type;//selector variable
    cout<<"Please enter 1 for shape of Point type"<<endl;
    cout<<"Please enter 2 for shape of Line type"<<endl;
    //cout<<"Please enter 3 for shape of Circle type"<<endl;
    cin>>type;
     
    //assigns the user given type to the variant
    if(type==1){//creates a point and returns it
    return Point();
    }
    else if(type==2){//creates a line and returns it
    return Line();
    }
    /*else if(type==3){//creates a circle and returns it
    return Circle();
    }*/
    }
     
    //Visitor class
    class VisitorClass: public boost::static_visitor<void>{
    private:
    double m_dx;//x delta to move
    double m_dy;//y delta to move
    public:
    //==================================================================================================
    //modifiers
    //==================================================================================================
    //function that Visits a point and moves its X,Y values
    VisitorClass(double xval,double yval):m_dx(xval),m_dy(yval){
    }
     
    void operator()(Point& p) const{
    //modifies the values of the point according to the user given inputs
    p.X(p.X()+m_dx);
    p.Y(p.Y()+m_dy);
    }
     
    //function that Visits a Line and moves its X,Y values of the starting and ending points
    void operator()(Line& l) const{
    //modifies the values of the starting point according to the user given inputs
    //l.p1().X(l.p1().X()+m_dx);
    //l.p1().Y(l.p1().Y()+m_dy);
    l.GetStart().X(l.GetStart().X()+m_dx);
    l.GetStart().Y(l.GetStart().Y()+m_dx);
    
    
     
    //modifies the values of the ending point according to the user given inputs (scaled by 2)
    //l.p2().X(l.p2().X()+m_dx*2);
    //l.p2().Y(l.p2().Y()+m_dy*2);
    l.GetEnd().X(l.GetEnd().X()+m_dx*2);
    l.GetEnd().Y(l.GetEnd().Y()+m_dy*2);
    }
     
    //function that Visits a Circle and moves its X,Y values of its center
    /*void operator()(Circle& c) const{
    //modifies the values of the center point with the user given values
    c.centerPoint().X((c.centerPoint().X()+m_dx));
    c.centerPoint().Y((c.centerPoint().Y()+m_dy));
    c.radius(m_dx+m_dy);
    }*/
    };
     
    int main(){
     
    //========================================================================================================================
    // usage of variant data container
    //========================================================================================================================
     
    //Assigns a shape type via shape_type function
    ShapeType figure=shape_type();
     
    //prints the type of the figure given by the user
    const std::type_info &ti=figure.type();//captures the type
    cout<<"The created figure type is an object of the "<<ti.name()<<endl;//calls its names and prints it
    cout<<figure;//the user assignation is sent to the cout using the overloaded << operator in each shape class
     
    Line l("MyLine",Point(3,4),Point(6,8));//creates a Line
    try{
    boost::get<Line>(figure)=l;//assigns Line l to the figure variant
    }
    catch(boost::bad_get e){
    std::cout << "***********************bad get error**************************" <<std::endl;
    }
     
    boost::apply_visitor(VisitorClass(9,12),figure);//shifts the figure according to a user given values
    cout<<figure;//the user assignation is sent to the cout.
    return 0;
    }

  2. #2
    Join Date
    Jun 2012
    Posts
    127

    Re: boost Variant

    My project compile now but something going wrong , please help
    I attached two print screen
    first, is about if I choose Line class
    second, if I choose Point... This one very bad((( Even go to exception (((
    Many thanks in advance
    Code:
    //line.h
    #ifndef LINE_H
    #define LINE_H
    #include "Shape.h"
    #include "Point.h"
    #include <string>
    #include <iostream>
    using namespace std;
    class Line : public Shape
    {
    	 private:
          Point start; 
    	  Point end;
    
       public:
          //constructors and destructor
          Line();
          Line(Point P_start, Point P_end);
    	  Line(const Line& line) ; // line copy constructor
          ~Line();
    		
          //getters and setters
          void SetStart ( Point SomePoint);
          void SetEnd ( Point SomePoint);
          Point GetStart() const ;
          Point GetEnd() const;
    
    	  Line operator = (const Line& l) ; // 
    	 friend ostream& operator << (ostream& os , const Line& l);
    
    	  //other useful methods
          void ToString(); 
    };
    
    #endif
    
    //point.h
    #ifndef POINT_H 
    #define POINT_H
    #include "Shape.h"
    #include <iostream>
    #include <string>
    using namespace std;
    class Point : public Shape
    
    {
    	private:
    double Xcoord;
    double Ycoord;
    
    	public:
    Point();
    Point (double xNew, double yNew);
    Point(const Point& point); // copy constructor for Point
    ~Point();
          
    void X( double Value);
    void Y( double Value);
    double X() const ;
    double Y() const ;
    Point operator = (const Point& p); // for Point class
    friend ostream& operator << ( ostream& os ,const  Point& p);
    void ToString();
    
    };
    
    #endif 
    
    // shape.h 
    #ifndef Shape_h 
    #define Shape_h
    #include <iostream>
    #include "stdlib.h"
    #include "Shape.h"
    using namespace std; 
    class Shape
    {
    	protected: 
    int m_id;  // Add a data member for an id number of type int.
    	public: 
    int id; 
    int ID(); // return n_id data
    Shape(); // initialises the id using a random number
    Shape(const Shape &OtherShape); // copies the id member
    Shape operator = (const Shape &OtherShape); // copies the id member
    virtual void ToString() ; // returns the id as string e.g. “ID: 123”
    };
    #endif 
    
    //line.cpp
    #include <iostream>
    //#include <math.h>
    #include "line.h"
    #include "Point.h"
    #include "Shape.h"
    #include <string>
    using namespace std;
    
    Line::Line(){}
    
    Line::Line(Point P_start, Point P_end)
    	: start(P_start), end(P_end) {}
    
    Line::Line(const Line& line) 
    {
    	start = line.start;
    	end = line.end;
    }
    
    Line Line::operator = (const Line& l) 
    	 {
    	if (this == &l)
    	{
    		return * this; 
    	}
    	/*member function from base class */
    	m_id = l.m_id;
    	/* data from derived class*/
    	start = l.start;
    	end = l.end;
    	return *this ;
    	} 
    
    Line::~Line() {}
    
    void Line::SetStart( Point SomePoint)
    	{
       start = SomePoint;
    	}
    
    void Line::SetEnd ( Point SomePoint)
    	{
      end = SomePoint;
    	}
    
    Point Line::GetStart() const
    	{
       return start;
    	}
    
    Point Line::GetEnd() const
    	{
       return end;
    	}
    
    ostream& operator << ( ostream& os , const  Line& l)
    	{
    		os << "[" << l.GetStart() << "," << l.GetEnd() << "]";
    		return os ; 
    	}
    
    
    
    void Line::ToString()  // returns the line as string              
    	{
    	cout << "[[" 
    		 << start << "," << end << "]]" << endl;
    	}
    
    
    //Point.cpp
    #include <iostream>
    #include "Point.h"
    using namespace std;
    
    Point::Point() {}
    
     Point::Point (double xNew, double yNew)
    	 : Xcoord(xNew), Ycoord(yNew) {}
    
    Point::~Point() {} //Destructor
    
    Point::Point(const Point& point) // Point copy constructor
    {
        Xcoord = point.Xcoord;
        Ycoord = point.Ycoord;
    }
    
    
    void Point::X( double Value) 
    {//Assign X-coordinate the Value that is put into the main
        Xcoord = Value; 
    }
    
    void Point::Y( double Value) 
    {//Assing Y-coordinate the Value that is put into the main
        Ycoord = Value;
    }
    
    double Point::X()  const
    {
    return Xcoord;//Return X-coordinate
    }
    
    double Point::Y()  const
    {
    return Ycoord;//Return Y-coordinate
    }
    
    
    void Point::ToString()
    	{
    cout << "( " << X() << "," 
         << Y() << " )";
    	}
    
    Point Point::operator = (const Point& p)
    {
    	if (this == &p)
    	{
    		return * this; 
    	}	
    
    m_id = p.m_id;// member function from base class 	
    Xcoord = p.Xcoord;// data from derived class
    Ycoord = p.Ycoord;
    return *this; 
    } 
    
    
    
    
    ostream& operator << ( ostream& os , const  Point& p)
    	{
    		os << "[" << p.X() << "," << p.Y() << "]";
    		return os ; 
    	}
    
    
    
    //Shape.cpp 
    #include <iostream>
    #include "Shape.h"
    using namespace std; 
    
    
    Shape::Shape() // initialises the id using a random number
    	
    	{
    	m_id = rand();
    	///cout << "id of shape is: " << m_id << endl; 
    	}
    
    int Shape::ID() // retrieve the id of the shape
    	{
    	return m_id; 
    	}
    	
    void Shape::ToString() // returns the id as string              
    {
    	// cout << "ID: "<< ID(); 
    }
    
    Shape::Shape(const Shape &OtherShape)
    	{//copy constructor that copies the id member
    		id = OtherShape.m_id;
    	}
    	
    Shape Shape::operator = (const Shape& OtherShape)
    	{//assignment operator that copies the id member
    	
    	if (this == &OtherShape)
    		{
    			return *this;
    		}
    	m_id = OtherShape.m_id;
    	return *this; 
    	}
    
    
    
    //main.cpp
    //Variant
    
    #include "Point.h"//header file declaration of class Point
    #include "Line.h"//header file declaration of class Line
    //#include "Circle.h"//header file declaration of class Circle
    #include "Shape.h"//header file declaration of class Shape
    #include <boost/variant.hpp>//includes boost class for variant
    #include <iostream>// C++ style I/O using operator overloading
    #include <ostream>
    using namespace std;// The C++ logical collection of functions
     
     
    //defines a shape type that can be of the form Point, Line or Circle
    typedef boost::variant<Point, Line/*, Circle*/> ShapeType;
     
    //function that returns a variant with the specified shape
     
    ShapeType shape_type(){
    int type;//selector variable
    cout<<"Please enter 1 for shape of Point type"<<endl;
    cout<<"Please enter 2 for shape of Line type"<<endl;
    //cout<<"Please enter 3 for shape of Circle type"<<endl;
    cin>>type;
     
    //assigns the user given type to the variant
    if(type==1){//creates a point and returns it
    return Point();
    }
    else if(type==2){//creates a line and returns it
    return Line();
    }
    /*else if(type==3){//creates a circle and returns it
    return Circle();
    }*/
    }
     
    //Visitor class
    class VisitorClass: public boost::static_visitor<void>{
    private:
    double m_dx;//x delta to move
    double m_dy;//y delta to move
    public:
    //==================================================================================================
    //modifiers
    //==================================================================================================
    //function that Visits a point and moves its X,Y values
    VisitorClass(double xval,double yval):m_dx(xval),m_dy(yval){
    }
     
    void operator()(Point& p) const{
    //modifies the values of the point according to the user given inputs
    p.X(p.X()+m_dx);
    p.Y(p.Y()+m_dy);
    }
     
    //function that Visits a Line and moves its X,Y values of the starting and ending points
    void operator()(Line& l) const{
    //modifies the values of the starting point according to the user given inputs
    //l.p1().X(l.p1().X()+m_dx);
    //l.p1().Y(l.p1().Y()+m_dy);
    l.GetStart().X(l.GetStart().X()+m_dx);
    l.GetStart().Y(l.GetStart().Y()+m_dx);
    
    
     
    //modifies the values of the ending point according to the user given inputs (scaled by 2)
    //l.p2().X(l.p2().X()+m_dx*2);
    //l.p2().Y(l.p2().Y()+m_dy*2);
    l.GetEnd().X(l.GetEnd().X()+m_dx*2);
    l.GetEnd().Y(l.GetEnd().Y()+m_dy*2);
    }
     
    //function that Visits a Circle and moves its X,Y values of its center
    /*void operator()(Circle& c) const{
    //modifies the values of the center point with the user given values
    c.centerPoint().X((c.centerPoint().X()+m_dx));
    c.centerPoint().Y((c.centerPoint().Y()+m_dy));
    c.radius(m_dx+m_dy);
    }*/
    };
     
    int main(){
     
    //========================================================================================================================
    // usage of variant data container
    //========================================================================================================================
     
    //Assigns a shape type via shape_type function
    ShapeType figure=shape_type();
     
    //prints the type of the figure given by the user
    const std::type_info &ti=figure.type();//captures the type
    cout<<"The created figure type is an object of the "<<ti.name()<<endl;//calls its names and prints it
    cout<<figure;//the user assignation is sent to the cout using the overloaded << operator in each shape class
     
    Line l(Point(3,4),Point(6,8));//creates a Line
    try{
    boost::get<Line>(figure)=l;//assigns Line l to the figure variant
    }
    catch(boost::bad_get e){
    std::cout << "***********************bad get error**************************" <<std::endl;
    }
     
    boost::apply_visitor(VisitorClass(9,12),figure);//shifts the figure according to a user given values
    cout<<figure;//the user assignation is sent to the cout.
    return 0;
    }
    help1.jpghelp2.jpg

  3. #3
    Join Date
    Apr 1999
    Posts
    27,449

    Re: boost Variant

    Quote Originally Posted by oteel View Post
    My project compile now but something going wrong , please help
    I attached two print screen
    1) Please format your code so that it's properly indented and readable. You keep posting code that is formatted all over the place, making it very difficult to read.

    2) Quit writing functions that are totally unnecessary. Why are you writing user-defined copy constructors and assignment operators for your classes? The default ones are perfectly acceptable -- you don't need to write any of these functions. If you keep writing functions that are unnecessary, all that does is make it easier for bugs to occur.

    3) Why are you not debugging your code? Programming is more than just writing code, running it, and if something goes wrong, post a message on CodeGuru. You have to show that you've made the attempt to debug your code yourself.

    4) Post each file in separate code blocks. Mushing everything into one huge code block makes it very difficult to see what's going on.

    Regards,

    Paul McKenzie

  4. #4
    Join Date
    Apr 1999
    Posts
    27,449

    Re: boost Variant

    First, take each class. All of them have either mistakes, unnecessary includes/code:

    Shape.h
    Code:
    #ifndef Shape_h
    #define Shape_h
    
    class Shape
    {
        protected:
            int m_id; // Add a data member for an id number of type int.
    
        public:
            int id;      // what is this for??
            int ID() const;   
            Shape();    
            virtual void ToString();      
            virtual ~Shape() {}
    };
    #endif
    1) Note that there are no includes, because nothing in that file uses anything in <string> or any other header you used. In your original file, you were including "Shape.h" inside of shape.h. Why were you doing this? For Windows, that results in a circular include, resulting in the code not compiling.

    2) You are deriving from Shape, therefore it needs to have a virtual destructor. Do you know why a virtual destructor is needed for Shape? If not, there are plenty of explanations of this, and I just don't have the time to repost why you need one.

    3) Why is there an id member variable?

    4) The copy constructor and assignment operator, and destructor have been removed. Again, there is no need to write these functions.


    Here is Point.h:
    Code:
    #ifndef POINT_H
    #define POINT_H
    
    #include "Shape.h"
    #include <ostream>
    
    class Point : public Shape
    {
        private:
            double Xcoord;
            double Ycoord;
        public:
            Point();
            Point(double xNew, double yNew);
    
            void X(double Value);
            void Y(double Value);
            double X() const;
            double Y() const;
            friend std::ostream & operator <<( std::ostream &os, const Point &p );
            void ToString();
    };
    #endif
    1) There is no "using namespace std" in a header. Again, this has been mentioned many times why you shouldn't do this.

    2) The only #include required is "Shape.h" and <ostream>.

    3) The copy constructor and assignment operator, and destructor have been removed. Again, there is no need to write these functions.

    Here is Line.h:
    Code:
    #ifndef LINE_H
    #define LINE_H
    #include "Shape.h"
    #include "Point.h"
    #include <ostream>
    
    class Line : public Shape
    {
        private:
    
            Point start;
            Point end;
    
        public:
            //constructors and destructor
            Line();
            Line(const Point& P_start, const Point& P_end);
    
            //getters and setters
            void SetStart(const Point& SomePoint);
            void SetEnd(const Point& SomePoint);
            Point GetStart() const;
            Point GetEnd() const;
    
            friend std::ostream & operator <<( std::ostream &os, const Line &l );
    
            //other useful methods
            void ToString();
    };
    #endif
    1) There is no "using namespace std" in a header. Again, this has been mentioned many times why you shouldn't do this.

    2) The only #include required is "Point.h", Shape.h and <ostream>.

    3) The copy constructor and assignment operator, and destructor have been removed. Again, there is no need to write these functions.

    4) Pass objects by reference or const reference, not by value. Only on rare occasions are objects passed by value (functors, for example).

    Given this, the implementations now are easier to maintain due to the irrelevant functions being removed.

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; July 4th, 2012 at 12:40 PM.

  5. #5
    Join Date
    Apr 1999
    Posts
    27,449

    Re: boost Variant

    The cpp files:

    Here is Shape.cpp:
    Code:
    #include <cstdlib>
    #include "Shape.h"
    
    Shape::Shape( ) : m_id(rand())
    { }
    
    int Shape::ID() const
    { return m_id; }
    
    void Shape::ToString( ) 
    { }
    Here is Point.cpp:
    Code:
    #include <iostream>
    #include "Point.h"
    
    using namespace std;
    
    Point::Point( ) { }
    
    Point::Point( double xNew, double yNew ) :Xcoord(xNew), Ycoord(yNew) 
    { }
    
    Point::Point( const Point &point ) : Xcoord(point.Xcoord), Ycoord(point.Ycoord)
    { }
    
    void Point::X( double Value ) 
    {  Xcoord = Value; }
    
    void Point::Y( double Value )
    { Ycoord = Value; }
    
    double Point::X( ) const
    { return Xcoord; }
    
    double Point::Y( ) const
    { return Ycoord; }
    
    void Point::ToString( )
    {
        cout << "( " << X() << "," << Y() << " )";
    }
    
    ostream & operator <<( ostream &os, const Point &p )
    {
        os << "[" << p.X() << "," << p.Y() << "]";
        return os;
    }
    Here is Line.cpp
    Code:
    #include <iostream>
    #include "line.h"
    
    using namespace std;
    
    Line::Line( ) { }
    
    Line::Line( const Point& P_start, const Point& P_end ) : start(P_start), end(P_end) { }
    
    void Line::SetStart( const Point& SomePoint )
    { start = SomePoint; }
    
    void Line::SetEnd( const Point& SomePoint )
    { end = SomePoint; }
    
    Point Line::GetStart() const
    { return start; }
    
    Point Line::GetEnd() const
    { return end; }
    
    ostream & operator <<( ostream &os, const Line &l )
    {
        os << "[" << l.GetStart() << "," << l.GetEnd() << "]";
        return os;
    }
    
    void Line::ToString( ) // returns the line as string
    {
        cout << "[["
            << start << "," << end << "]]" << endl;
    }
    I didn't compile all of this, but the point is that the code is simpler. There are no copy constructors or assignment operators to mess up or other unnecessary functions.

    The next step for you is to take a simple main() program that uses the boost classes and make sure you know how to use them before you write or call other functions that do something much more complex. If you believe you can use boost::any correctly and call of these visitor pattern functions, then there really isn't any need for you to ask us to debug your code, since these items assume you're an intermediate to advanced C++ programmer.

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; July 4th, 2012 at 12:56 PM.

  6. #6
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    6,765

    Re: boost Variant

    Note that if you're following Paul McKenzie's examples, you will find that you don't need operator<< to be a friend. Furthermore, ToString does not need to be a member since you can call the GetStart and GetEnd member functions instead of accessing the member variables directly.
    C + C++ Compiler: MinGW port of GCC
    Build + Version Control System: SCons + Bazaar

    Look up a C/C++ Reference and learn How To Ask Questions The Smart Way
    Kindly rate my posts if you found them useful

  7. #7
    Join Date
    Jun 2012
    Posts
    127

    Re: boost Variant

    Quote Originally Posted by Paul McKenzie View Post
    The cpp files:

    Here is Shape.cpp:
    Code:
    #include <cstdlib>
    #include "Shape.h"
    
    Shape::Shape( ) : m_id(rand())
    { }
    
    int Shape::ID() const
    { return m_id; }
    
    void Shape::ToString( ) 
    { }
    Here is Point.cpp:
    Code:
    #include <iostream>
    #include "Point.h"
    
    using namespace std;
    
    Point::Point( ) { }
    
    Point::Point( double xNew, double yNew ) :Xcoord(xNew), Ycoord(yNew) 
    { }
    
    Point::Point( const Point &point ) : Xcoord(point.Xcoord), Ycoord(point.Ycoord)
    { }
    
    void Point::X( double Value ) 
    {  Xcoord = Value; }
    
    void Point::Y( double Value )
    { Ycoord = Value; }
    
    double Point::X( ) const
    { return Xcoord; }
    
    double Point::Y( ) const
    { return Ycoord; }
    
    void Point::ToString( )
    {
        cout << "( " << X() << "," << Y() << " )";
    }
    
    ostream & operator <<( ostream &os, const Point &p )
    {
        os << "[" << p.X() << "," << p.Y() << "]";
        return os;
    }
    Here is Line.cpp
    Code:
    #include <iostream>
    #include "line.h"
    
    using namespace std;
    
    Line::Line( ) { }
    
    Line::Line( const Point& P_start, const Point& P_end ) : start(P_start), end(P_end) { }
    
    void Line::SetStart( const Point& SomePoint )
    { start = SomePoint; }
    
    void Line::SetEnd( const Point& SomePoint )
    { end = SomePoint; }
    
    Point Line::GetStart() const
    { return start; }
    
    Point Line::GetEnd() const
    { return end; }
    
    ostream & operator <<( ostream &os, const Line &l )
    {
        os << "[" << l.GetStart() << "," << l.GetEnd() << "]";
        return os;
    }
    
    void Line::ToString( ) // returns the line as string
    {
        cout << "[["
            << start << "," << end << "]]" << endl;
    }
    I didn't compile all of this, but the point is that the code is simpler. There are no copy constructors or assignment operators to mess up or other unnecessary functions.

    The next step for you is to take a simple main() program that uses the boost classes and make sure you know how to use them before you write or call other functions that do something much more complex. If you believe you can use boost::any correctly and call of these visitor pattern functions, then there really isn't any need for you to ask us to debug your code, since these items assume you're an intermediate to advanced C++ programmer.

    Regards,

    Paul McKenzie
    Thank you very much !

  8. #8
    Join Date
    Jun 2012
    Posts
    127

    Re: boost Variant

    Quote Originally Posted by oteel View Post
    Thank you very much !
    Now everything fine with Point class but Line class don't work correctly. The problem is when I choice line class it gives me value that I set up in default constructor and don't change value after called visitor.
    Now I set up in default constructor in Line class [(1,2) (3,1)]... but I need that code gives me value of MyLine [(3,4,) (6,8)]

    What wrong with Line class
    last edition:
    Code:
    [CPP]// line.h
    #ifndef LINE_H
    #define LINE_H
    #include "Shape.h"
    #include "Point.h"
    #include <ostream>
    
    class Line : public Shape
    {
         private:
          Point start; 
         // string discrib;
          Point end;
     
       public:
          //constructors and destructor
          Line();
          Line(  Point& P_start,  Point& P_end);
          Line(const Line& line); // line copy constructor
          ~Line();
            
          //getters and setters
          void SetStart (  Point& SomePoint);
          void SetEnd (  Point& SomePoint);
          Point GetStart() const ;
          Point GetEnd() const ;
     
          Line& operator = ( const Line& l);
          friend ostream& operator << (ostream& os , const Line& l);
     
          //other useful methods
          void ToString() const; 
    };
    
    #endif 
    
    //point.h
    #ifndef POINT_H
    #define POINT_H
    
    #include "Shape.h"
    #include <ostream>
    class Point : public Shape
     
    {
        private:
    double Xcoord;
    double Ycoord;
     
        public:
    Point();
    Point (double xNew, double yNew);
    Point( const Point& point); // copy constructor for Point
    ~Point();
          
    void X( double Value);
    void Y( double Value);
    double X() const;
    double Y() const;
     
    Point& operator = ( const Point& p);
    friend ostream& operator << (ostream& os ,  const Point& p);
    void ToString() const;
     
    };
    
    #endif 
    
    #ifndef Shape_h
    #define Shape_h
    #include <string>
    #include <iostream>
    using namespace std;
     
    // shape.h 
    class Shape
    {
        protected: 
    int m_id;  // Add a data member for an id number of type int.
        public: 
    int id; 
    int ID() const; // return n_id data
    Shape(); // initialises the id using a random number
    Shape(const Shape &OtherShape); // copies the id member
    Shape& operator = (const Shape &OtherShape); // copies the id member
    virtual void ToString() const ; // returns the id as string e.g. “ID: 123”
    };
     
    
    #endif 
    
    //line.cpp
    #include <iostream>
    #include "line.h"
    
    using namespace std;
    Line::Line():start(Point(1, 2)), end(Point(3, 1)){}
     
    Line::Line( Point& P_start,  Point& P_end)
        : start(P_start), end(P_end) {}
     
    Line::Line( const Line& line)
    {
        start = line.start;
        end = line.end;
    }
     
    Line::~Line() {}
     
    void Line::SetStart(  Point& SomePoint)
        {
       start = SomePoint;
        }
     
    void Line::SetEnd (  Point& SomePoint)
        {
      end = SomePoint;
        }
     
    Point Line::GetStart() const
        {
       return start;
        }
     
    Point Line::GetEnd() const
        {
       return end;
        }
     
    Line& Line::operator = ( const Line& l)
         {
        if (this == &l)
        {
            return * this; 
        }
        /*member function from base class */
        m_id = l.m_id;
        /* data from derived class*/
       
        start = l.start;
        end = l.end;
        return *this ;
        } 
     
     
     
    void Line::ToString() const  // returns the line as string              
        {
        cout << "[["  
             << start << "," << end << "]]" << endl;
        }
     
     
    ostream& operator << ( ostream& os , const  Line& l)
        {
            os << "[" << l.GetStart() << "," << l.GetEnd() << "]";
            return os ; 
        }
    
    //Point.cpp
     #include <iostream>
    #include "Point.h"
    
    using namespace std;
    
    Point::Point() : Xcoord(0), Ycoord(0) {}
     
     Point::Point (double xNew, double yNew)
         : Xcoord(xNew), Ycoord(yNew) {}
     
    Point::~Point() {} //Destructor
     
    Point::Point( const Point& point) // Point copy constructor
    {
        Xcoord = point.Xcoord;
        Ycoord = point.Ycoord;
    }
     
     
    void Point::X( double Value) 
    {//Assign X-coordinate the Value that is put into the main
        Xcoord = Value; 
    }
     
    void Point::Y( double Value) 
    {//Assing Y-coordinate the Value that is put into the main
        Ycoord = Value;
    }
     
    double Point::X()  const
    {
    return Xcoord;//Return X-coordinate
    }
     
    double Point::Y()  const
    {
    return Ycoord;//Return Y-coordinate
    }
     
     
    void Point::ToString() const
        {
    cout << "( " << X() << "," 
         << Y() << " )";
        }
     
    Point& Point::operator = ( const Point& p)
    {
        if (this == &p)
        {
            return * this; 
        }   
     
    m_id = p.m_id;// member function from base class    
    Xcoord = p.Xcoord;// data from derived class
    Ycoord = p.Ycoord;
    return *this; 
    }
     
    ostream& operator << (ostream& os ,  const Point& p)
        {
            os << "[" << p.X() << "," << p.Y() << "]";
            return os ; 
        }
     
     
    
     
    //Shape.cpp 
    #include <iostream>
    #include "Shape.h"
    
    //using namespace std; 
    
    
    
    Shape::Shape() // initialises the id using a random number
    	
    	{
    	m_id = rand();
    	///cout << "id of shape is: " << m_id << endl; 
    	}
    
    int Shape::ID() const // retrieve the id of the shape
    	{
    	return m_id; 
    	}
    	
    void Shape::ToString()  const// returns the id as string              
    {
    	// cout << "ID: "<< ID(); 
    }
    
    Shape::Shape(const Shape &OtherShape)
    	{//copy constructor that copies the id member
    		id = OtherShape.m_id;
    	}
    	
    Shape& Shape::operator = (const Shape& OtherShape)
    	{//assignment operator that copies the id member
    	
    	if (this == &OtherShape)
    		{
    			return *this;
    		}
    	m_id = OtherShape.m_id;
    	return *this; 
    	}
    
    
    
    //main.cpp
    
    #include "Point.h"					//header file declaration of class Point
    #include "Line.h"					//header file declaration of class Line
    //#include "Circle.h"				//header file declaration of class Circle
    #include "Shape.h"					//header file declaration of class Shape
    #include <boost/variant.hpp>		//includes boost class for variant
    #include <iostream>					// C++ style I/O using operator overloading
    #include <ostream>
    using namespace std;				// The C++ logical collection of functions
     
     
    //defines a shape type that can be of the form Point, Line or Circle
    typedef boost::variant<Point, Line/*, Circle*/> ShapeType;
     
    //function that returns a variant with the specified shape
     
    ShapeType shape_type()
    {
    int type;//selector variable
    cout<<"Please enter 1 for shape of Point type"<<endl;
    cout<<"Please enter 2 for shape of Line type"<<endl;
    //cout<<"Please enter 3 for shape of Circle type"<<endl;
    cin>>type;
     
    //assigns the user given type to the variant
    	if(type==1)
    		{						//creates a point and returns it
    		return Point();
    		}
    	else if(type==2)
    		{				//creates a line and returns it
    		return Line();
    		}
    /*else if(type==3){//creates a circle and returns it
    return Circle();
    }*/
    }
     
    //Visitor class
    class VisitorClass: public boost::static_visitor<void>
    {
    private:
    double m_dx;//x delta to move
    double m_dy;//y delta to move
    public:
    //==================================================================================================
    //modifiers
    //==================================================================================================
    //function that Visits a point and moves its X,Y values
    	VisitorClass(double xval,double yval):m_dx(xval),m_dy(yval) {}
    
     
    void operator()(Point& p) const 
    {
    //modifies the values of the point according to the user given inputs
    p.X(p.X()+m_dx);
    p.Y(p.Y()+m_dy);
    }
     
    //function that Visits a Line and moves its X,Y values of the starting and ending points
    void operator()(Line& l) const 
    {
    //modifies the values of the starting point according to the user given inputs
    //l.p1().X(l.p1().X()+m_dx);
    //l.p1().Y(l.p1().Y()+m_dy);
    //l.GetStart().X(l.GetStart().X()+m_dx);
    //l.GetStart().Y(l.GetStart().Y()+m_dx);
    l.GetStart().X(l.GetStart().X()+m_dx);
    l.GetStart().Y(l.GetStart().Y()+m_dx);
    
    
     
    //modifies the values of the ending point according to the user given inputs (scaled by 2)
    //l.p2().X(l.p2().X()+m_dx*2);
    //l.p2().Y(l.p2().Y()+m_dy*2);
    l.GetEnd().X(l.GetEnd().X()+m_dx*2);
    l.GetEnd().Y(l.GetEnd().Y()+m_dy*2);
    }
     
    //function that Visits a Circle and moves its X,Y values of its center
    /*void operator()(Circle& c) const{
    //modifies the values of the center point with the user given values
    c.centerPoint().X((c.centerPoint().X()+m_dx));
    c.centerPoint().Y((c.centerPoint().Y()+m_dy));
    c.radius(m_dx+m_dy);
    }*/
    };
     
    int main(){
    
    //========================================================================================================================
    // usage of variant data container
    //========================================================================================================================
     Point p(11,1);
     Point p1(2,2);
     Point p2(3,3);
    Line l(Point(3,4),Point(6,8));
    //Assigns a shape type via shape_type function
    ShapeType figure=shape_type();
     cout << "\n\n\t myLine" << l << "\n\n\t";
    
      try
    {
    
    
    switch (figure.which())
    {
    case 0: cout << "\n\n\tPoint"; break;
    case 1: cout << "\n\n\tLine"; break;
    default : cout << "invalide input" ; 
    }
    
    
    //the user assignation is sent to the cout using the overloaded << operator in each shape class
    
    //creates a Line
    
    	
    boost::get<Point>(figure)=p;//assigns Line l to the figure variant
    boost::get<Line>(figure)=l;//assigns Line l to the figure variant
    }
    catch(boost::bad_get e)
    {
    std::cout << "\n\n\t***********************bad get error**************************" <<std::endl;
    }
    
     cout<<"\n\n\t BEFORE VISITOR "<< figure << "\n\n\t ";
    boost::apply_visitor(VisitorClass(9,12),figure);//shifts the figure according to a user given values
    cout<<"\n\n\t AFTER VISITOR "<<figure;//the user assignation is sent to the cout.
    cout << "\n\n\t";
    system ("pause");
    return 0;
    }[/CPP]
    Attached Images Attached Images

  9. #9
    Join Date
    Apr 1999
    Posts
    27,449

    Re: boost Variant

    Quote Originally Posted by oteel View Post
    Now everything fine with Point class but Line class don't work correctly.
    Again, if you quit writing functions you don't need to write, things become much simpler and you would have less bugs.

    First:
    Code:
    Line::Line( const Line& line)
    {
        start = line.start;
        end = line.end;
    }
    You are now in trouble, since you did not take care of the base class. In other words, you have a bogus copy of the Line class because Shape was not copied.

    Then you have this:
    Code:
    Line& Line::operator = ( const Line& l)
         {
        if (this == &l)
        {
            return * this; 
        }
        /*member function from base class */
        m_id = l.m_id;
        /* data from derived class*/
       
        start = l.start;
        end = l.end;
        return *this ;
        }
    So what happens if Shape changes and adds a member variable? You now have to change this too. You cannot assume what "Shape" has as member variables.

    The bottom line is that you don't need to write these functions at all for the classes you have. All of the members are safely copyable by themselves without you having to do anything. So really, get rid of these functions..

    Let me ask you -- do you know what the compiler generated copy constructor and assignment operator do? If you did know, you would know that you don't need to write these functions yourself. The compiler generated version will never get this wrong, so let the compiler handle the copying. By you telling the compiler that you can write your own copy constructors and assignment operators, all the responsibility of writing them correctly is yours, and you failed.

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; July 22nd, 2012 at 10:46 AM.

  10. #10
    Join Date
    Jun 2012
    Posts
    127

    Re: boost Variant

    Quote Originally Posted by Paul McKenzie View Post
    Again, if you quit writing functions you don't need to write, things become much simpler and you would have less bugs.

    First:
    Code:
    Line::Line( const Line& line)
    {
        start = line.start;
        end = line.end;
    }
    You are now in trouble, since you did not take care of the base class. In other words, you have a bogus copy of the Line class because Shape was not copied.

    Then you have this:
    Code:
    Line& Line::operator = ( const Line& l)
         {
        if (this == &l)
        {
            return * this; 
        }
        /*member function from base class */
        m_id = l.m_id;
        /* data from derived class*/
       
        start = l.start;
        end = l.end;
        return *this ;
        }
    So what happens if Shape changes and adds a member variable? You now have to change this too. You cannot assume what "Shape" has as member variables.

    The bottom line is that you don't need to write these functions at all for the classes you have. All of the members are safely copyable by themselves without you having to do anything. So really, get rid of these functions..

    Let me ask you -- do you know what the compiler generated copy constructor and assignment operator do? If you did know, you would know that you don't need to write these functions yourself. The compiler generated version will never get this wrong, so let the compiler handle the copying. By you telling the compiler that you can write your own copy constructors and assignment operators, all the responsibility of writing them correctly is yours, and you failed.

    Regards,

    Paul McKenzie

    I not quit understand your idea... What should I do to resolve my problem belong Line class


    About your idea you try to say that I should add to Shape class data member function that will be inherent by Point or Line class ?

    or You mean that I should make explicit inheritance between derived and base classes constructors

    Like this ...

    Code:
    Line::Line( Point& P_start,  Point& P_end) : Shape ()
    {
    start = P_start ; 
    end = P_end; 
    }
    But , nothing happen when I try make constructor inheritance, in this way

    BTW, then I comment out copy constructor or assignment operator from Line class compiler gives me linked error...

  11. #11
    Join Date
    Jun 2012
    Posts
    127

    Re: boost Variant

    But if you mean add new data member to Shape class why Point class works well ?

  12. #12
    Join Date
    Apr 1999
    Posts
    27,449

    Re: boost Variant

    Quote Originally Posted by oteel View Post
    I not quit understand your idea... What should I do to resolve my problem belong Line class
    Again, get out of the business of writing copy constructors and assignment operators. There is no need for you to write these functions at all. This is for all of your classes.

    I'll answer you, just for your information. The reason why the Line copy constructor is wrong is this: you are taking an existing Line object and copying it to a new Line object. That existing Line object has a base class Shape. That Shape part of the Line object needs to be copied too -- if not, you get a new Line object with some members set correctly, but the base class members set incorrectly.

    When you copy, you must copy everything from the existing object. This includes invoking the base class copy constructor. Look at this simple example:
    Code:
    class Base
    {
        int m_x;
        public:
            Base(int  x = 0 ) : m_x(x) { }
    };
    
    class Derived : public Base
    {
        int m_d;
        public:
            Derived(int d) : m_d(d), Base(d) { }
     
           // Now let me try to outsmart the compiler and write my own (wrong) copy ctor
            Derived(const Derived& obj)
            {
               m_d = obj.m_d;
            }
    };
    
    int main()
    {
        Derived d1(10);
        Derived d2(d1);   // you're in trouble
    }
    The reason why the second line in main() causes a problem is that d2 will have m_d set, but what about the m_x (the member in the base class)? When I run the code above, d2 has its m_x member set to 0, but in d1, m_x it is set to 10. So d2 is not equal to d1 -- you don't have a real copy, you have a "half-copy" masquerading as a real copy.

    These errors are some of the hardest to find when your program starts running. In the example above, if I were to use d2 assuming that it is an exact copy of d1, my program will not run correctly. Now when you write functions that return objects by value, or you start to use other classes that use value types (for example any of the STL container classes), your wrong copy constructor messes up everything, things go haywire, and your program blows up.

    The example above is exactly what you're doing with your Line copy constructor. So how do you fix it? The best way to fix it is to not write the copy constructor. Let the compiler do the copy -- the compiler will do it correctly, doesn't make mistakes, goes through all of the members (including ones in base classes) and makes the copies, etc. Why do you want to do this work yourself?

    Assuming all of the members are safely copyable, what if your class had 50 member variables? Would you write the code to copy 50 members? How about 100 member variables? Won't you get tired at some point writing all of this code to make the copies? What if you forget to copy the 27th member variable (maybe your eyes got tired and missed it)? You now have a bug in your program because you missed copying that member variable. What if you have a class D, derived from class C, which is derived from class B, which is derived from class A? Are you going to go through all of those classes and write copy constructors and assignment operators, and then hoping you didn't miss anything when copying all of these objects?

    The time when you need to code your own copy ctor and assignment operator is when the default compiler versions are not adequate. For example, if your class contains a pointer to dynamically allocated memory and you need to do a deep copy (the default versions only do shallow copies). But again, all of your classes you wrote Shape, Line, and Point have members that all they need are shallow copies, that's why you don't need to write these functions and instead let the compiler do the work for you.

    But just for completeness, let's assume you did need to write a copy constructor. For the simple code I wrote above:
    Code:
            Derived(const Derived& obj) : Base(obj)
            {
               m_d = obj.m_d;
            }
    Note what's in red.

    The same issue is the same with the assignment operator. You must make sure that the assignment of the base object is done so that you don't have bad copies, but again, there is no need to write assignment operators for the same reason there is no reason for you to write copy constructors.

    or You mean that I should make explicit inheritance between derived and base classes constructors

    Like this ...

    Code:
    Line::Line( Point& P_start,  Point& P_end) : Shape ()
    {
    start = P_start ; 
    end = P_end; 
    }
    That is not a copy constructor.
    BTW, then I comment out copy constructor or assignment operator from Line class compiler gives me linked error...
    Then you didn't comment out all of the code concerning copy constructor and assignment operator .

    All of the classes and structs that a C++ programmer writes have available copy constructors and assignment operators if these functions are not written by the programmer.. The only way for a copy constructor/assignment operator to give you a linker error is if you attempted to write your own copy assignment operator and you didn't implement it.

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; July 22nd, 2012 at 09:22 PM.

  13. #13
    Join Date
    Apr 1999
    Posts
    27,449

    Re: boost Variant

    Quote Originally Posted by oteel View Post
    But if you mean add new data member to Shape class why Point class works well ?
    You made the same mistake as the Line class. Your Point class will not work "well" in anything but a toy program. If you don't believe me, copy a Point object to another Point object. You should see that the Shape part of the new Point object is incorrect.

    You will have two Point objects that are not really copies of each other, but are saying to the whole world that they are copies. Somewhere in a real program, the lie that the two objects are real copies will crash a program, and you now have to spend sleepness nights finding and fxing that bug.

    Secondly, never say "it works well" if you make mistakes like this -- you should know by now that if you have bugs in a C++ program like this, the behaviour of the program is undefined.

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; July 22nd, 2012 at 05:46 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured