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,...
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++;
}
}
};
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With