C ++ templates, effective function for loading points

I would like to implement the function of loading 1D / 2D / 3D points from a file ... The parameter of the Point template can be a one-dimensional 2D 3D point.

template <typename Point>
void List <Point> ::load ( const char *file)
{

            ...

            for ( unsigned int i = 0; i < file.size(); i++ )
            {

                   if ( file[i].size() == 1 )
                    {
                            items.push_back( Point ( atof ( file[i][0].c_str() ) ) );
                    }

                    else if ( file[i].size() == 2 )
                    {
                            items.push_back( Point ( atof ( file[i][0].c_str() ), atof ( file[i][1].c_str() ) ) );
                    }

                    else if ( file[i].size() == 3 )
                    {
                            items.push_back(Point ( atof ( file[i][0].c_str() ), atof ( file[i][1].c_str() ), atof ( file[i][2].c_str() ) ) );
                    }
            }
 }

If I ran this function for a 2D point, then there is no constructor with three parameters in the 2D point. The same situation arises for a 3D point ...

List <Point2D> list1;
list1.load("file");  //Error
List <Point3D> list2;
list2.load("file");  //Error

Error   275 error C2661 : no overloaded function takes 3 arguments
Error   275 error C2661 : no overloaded function takes 2 arguments  

How to effectively create such a function? The syntax is somewhat simplified, this is just an illustrative example.

+3
source share
4 answers

, , : Point, () 1 , Point 2 , Point 3- . .

Point, 1 3 . , , , [i].size().

: , Point, , , [i].size() == 3? ?

, , . , , 1, 2 3 . , - :

template <typename Point, int N>
Point construct_point(const vector<string>& line);

template <typename Point>
Point construct_point<Point, 1>(const vector<string>& line)
{
    assert(line.size() == 1);
    return Point(atof ( line[0].c_str() ));
}

template <typename Point>
Point construct_point<Point, 2>(const vector<string>& line)
{
    assert(line.size() == 2);
    return Point(atof ( line[0].c_str() ), atof ( line[1].c_str() ));
}

template <typename Point>
Point construct_point<Point, 3>(const vector<string>& line)
{
    assert(line.size() == 3);
    return Point(atof ( line[0].c_str() ), atof ( line[1].c_str() ), atof ( line[2].c_str() ));
}

template <typename Point>
void List<Point>::load (const char *file)
{
    ...

    for (unsigned i = 0; i < lines.size(); ++i)
    {
         // Assume each Point class declares a static constant integer named 'dimension'
         // which is its dimension.
         items.push_back(construct_point<Point, Point::dimension>(lines[i]));
    }
    ...
}
+3

→ .

class Point2D {
    int x,y;
public:
    friend istream &operator>> (istream &input, Point2D &pt) {
        return input >> pt.x >> pt.y;
    }
};

class Point3D {
    int x,y,z;
public:
    friend istream &operator>> (istream &input, Point3D &pt) {
        return input >> pt.x >> pt.y >> pt.z;
    }
};

ifstream :

ifstream input("/tmp/points");
Point2D point2;
Point3D point3;
input >> point2 >> point3;
+2

. , , /.

+1

You can pass the number of point measurements as a parameter to the function template, and then call it list.load<2>("file"). And then you can specialize the functions to handle each case ... but, as someone pointed out, you should not worry too much about efficiency.

0
source

Source: https://habr.com/ru/post/1790809/


All Articles