Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++ read data from file and convert to template type of class

Following case:

template <typename NumberType = double>
class A
{
   //constructur, destructor,...

   //member variable
   std::vector<std::vector<NumberType> matrix_;

   //member function
   void read(std::ifstream fileIn)
   {
       std::string line, word;
       unsigned int row = 0;
       while (std::getline(fileIn, line))
       {
         std::istringstream lineStream(line);
         unsigned int col = 0;
         while (std::getline(lineStream, word, ','))
            {
               matrix_[row][col] = std::stod(word); // how to convert to NumberType?
               col++;
            }
         row++;
      }
   }
};

I read matrix-like data from a csv file and want to store the entries in a container, whose type is a template type from a class. At the moment, I instantiate the class only for NumberType = double , so I hard-coded std::stod(word) for testing.

But how can I convert the string word to NumberType? NumberType can be float, double, long double,..., but not string, unsigned int, int,...

like image 661
SolidMechanicsFan Avatar asked Sep 06 '25 08:09

SolidMechanicsFan


2 Answers

I would use explicit conversion functions for types you want to support. That way you will not leave conversion to chance (implicit conversions and/or probably incorrect casting).

#include <string>

template<typename NumberType>
NumberType ConvertTo(const std::string& from)
{
    static_assert(false, "no conversion for this type yet");
}

// provide specializations for supported conversions

template<>
double ConvertTo<double>(const std::string& from)
{
    return std::stod(from);
}

template<>
int ConvertTo<int>(const std::string& from)
{
    return std::stoi(from);
}


template <typename NumberType = double>
class A
{
    //constructur, destructor,...

    //member variable
    std::vector < std::vector<NumberType> matrix_;

    //member function
    void read(std::ifstream fileIn)
    {
        std::string line, word;
        unsigned int row = 0;
        while (std::getline(fileIn, line))
        {
            std::istringstream lineStream(line);
            unsigned int col = 0;
            while (std::getline(lineStream, word, ','))
            {
                // Use the template conversion function here :
                matrix_[row][col] = ConvertTo<NumberType>(word);
                col++;
            }
            row++;
        }
    }
};
like image 94
Pepijn Kramer Avatar answered Sep 09 '25 05:09

Pepijn Kramer


You can create a std::istringstream from word and then use its operator>> to parse the numeric value (as it has an overload for the standard numeric types).

You can add the method GetNumber below to your class, and use it instead of std::stod.

#include <sstream>
#include <iostream>

template <typename NumberType = double>
class A
{
    // ...

public:
    static NumberType GetNumber(std::string const& word)
    {
        std::istringstream ss{ word };
        NumberType val{};
        ss >> val; // here the proper overload will be called according to the type NumberType 
        return val;
    }
};

int main() 
{
    std::cout << A<float>::GetNumber("123.123") << "\n";
    std::cout << A<double>::GetNumber("456.456") << "\n";
}

Output:

123.123
456.456

Note:
The GetNumber method above is not actually related to class A and could be placed anywhere.
I posted it as a part of class A to match to OP's code, and make it clear where it should be used.

like image 20
wohlstad Avatar answered Sep 09 '25 05:09

wohlstad