Templates and string conversion - c++

I am creating a generic class that plans to read/write from a file.
Ergo I am unsure of what type will be instantiated.
How can I convert a string into some unknown type during the read stage?
IE
template<class T>
void fromString(std::string from, T to) {
to = from;
}
Anyway to do this without specializing for a numerous amount of classes?

The idiomatic way to do so is using something like this:
template<typename T>
void fromString(std::string from, T& to) {
std::istringstream iss(from);
iss >> to;
}
Most of the available standard specializations to parse the string input formats, would be covered by the already available std::istream& operator>>(std::istream&, T&); specializations.
Anyway to do this without specializing for a numerous amount of classes?
No, you still need to have specializations for various classes like
class Foo {
private:
int x;
double y;
public:
std::istream& getFromStream(std::istream& input) {
input >> x;
input >> y;
return input;
}
};
std:istream& operator>>(std::istream& is, Foo& subject) {
return subject.getFromStream(is);
}

Related

(De)serializing an enum class

I am trying to serialize and deserialize (using QDataStream but that is irrelevant here) an enum class variable:
enum class Type : char
{
Trivial,
Complex
};
The serialization is easy:
QDataStream &operator<<(QDataStream &stream, Type type)
{
return stream << static_cast<char>(type);
}
But the deserialization is not:
QDataStream &operator>>(QDataStream &stream, Type &type)
{
return stream >> static_cast<char &>(type);
}
Apparently the static_cast of reference to enum class to a reference to its underlying type is not allowed. Furthermore, the "obvious" solution:
QDataStream &operator>>(QDataStream &stream, Type &type)
{
return stream >> reinterpret_cast<char &>(type);
}
might actually be illegal and not defined by the standard according to the answer to this question because the equivalent expression return stream >> (*static_cast<char *>(static_cast<void *>(&type))); is declared as illegal there (or rather not defined by the standard). If that was the case I would need to do this:
QDataStream &operator>>(QDataStream &stream, Type &type)
{
char c = 0;
stream >> c;
type = static_cast<Type>(c);
return stream;
}
which is NOT pretty, is 4 lines instead of 1 etc. etc. And seems pretty unnecesasry to me for such a (seemingly) simple thing.
My question: Is the reinterpret_cast or equivalent static_cast via void* really illegal (undefined by standard) when casting a reference to enum class variable to a reference of its underlying type?
You could write a template function that will allow you to write 1 line for each operator>> that you define.
template <class UT, class S, class E> S& DeserializeEnumClassValue(S &s, E &e)
{
UT temp;
s >> temp;
e = static_cast<E>(temp);
return s;
}
And use it like that:
QDataStream &operator>>(QDataStream &stream, Type &type)
{
return DeserializeEnumClassValue<char>(stream, value);
}
But this can be improved using std::underlying_type (https://en.cppreference.com/w/cpp/types/underlying_type) as it is possible to get it at compile time.
If you take that approach, then you should also do something similar for operator<< to make maintenance easier.
I get the following solution:
template <typename T>
typename std::enable_if<std::is_enum<T>::value, QDataStream &>::type&
operator<<(QDataStream &s, const T &t)
{ return s << static_cast<typename std::underlying_type<T>::type>(t); }
template <typename T>
typename std::enable_if<std::is_enum<T>::value, QDataStream &>::type&
operator>>(QDataStream &s, T &t)
{ return s >> reinterpret_cast<typename std::underlying_type<T>::type &>(t); }
Which from github, and get verified in the src.
I feel that people often fall into the trap of language and cannot extricate themselves.If you use your hand to fill in the machine code, there is no problem, if you are not wrong.I mean if you have a hard time to come up with a counter-example,hope for some convenience and can tolerate possible mistakes,just do it.Otherwise, using the most secure method.

C++ Operator>> Overloading with Mutator?

I am trying to figure out a way (if possible) to overload the >> operator to function correctly with a mutator. For example, I want to write:
myClass obj;
cin >> obj.setValue;
and have it correctly set the obj's private value using the available mutator in a single line. I know I can use a temporary variable to store the cin and set the obj value with that, but I'm wondering if there is a more concise method such as this. I'm a novice programmer so this is my futile attempt within myClass:
friend std::istream &operator>>(std::istream &in, void (myClass::*pt)(double newValue)) {
double temp;
in >> temp;
pt(temp);
return in;
}
I know I can simply overload the myClass as a whole to accept:
cin >> myClass;
but this would prevent me from setting different individual values within myClass at different times.
Thanks
cin >> obj.setValue or cin >> &obj.setValue are examples of invalid C++. There's no way of getting a reference/pointer to a member function of a particular instance of a class.
What you could do is instead package the this pointer and a pointer to member function in a small struct, and overload operator>> on that instead:
template <typename T, typename Arg>
struct setter_t
{
T* _this;
void (T::*_ptr)(Arg);
};
template <typename T, typename Arg>
auto setter(T& x, void (T::*ptr)(Arg))
{
return setter_t<T, Arg>{&x, ptr};
}
template <typename T, typename Arg>
std::istream &operator>>(std::istream &in, setter_t<T, Arg> s)
{
Arg temp;
in >> temp;
(s._this->*s._ptr)(temp);
return in;
}
Usage:
myClass obj;
std::cin >> setter(obj, &myClass::setValue);
live wandbox example
Here's a C++17 solution that doesn't unnecessarily store _ptr inside setter_t. Usage:
std::cin >> setter<&myClass::setValue>(obj);
live wandbox example
You could make .setValue() return a non const reference to a Functor (a class that overrides the operator() ), then make that Functor override the
std::istream &operator>>(std::istream &is, MySetterFunctor &x){
double temp;
is >> temp;
x(temp);
return is;
}
The functor would be initialized by obj, receive a pointer to obj and use the actual obj's setter method in its
void operator()(double v){ obj->set_value(v);}
For that extra bit of hackery, you could make setValue a non-const public member so that you can just call it like std::cin >> obj.setValue and also normally do x.setValue(someDouble). You may make obj.set_value a protected member function and make MySetterFunctor a friend class of obj.
class Obj{
public:
friend class MySetterFunctor;
MySetterFunctor setValue;
...
}
Big disclaimer: This is all theoretical talk, I am not sure one would want to do this but I believe it would let you do what you want.

How to force std::stringstream operator >> to read an entire string?

How to force std::stringstream operator >> to read an entire string instead of stopping at the first whitespace?
I've got a template class that stores a value read from a text file:
template <typename T>
class ValueContainer
{
protected:
T m_value;
public:
/* ... */
virtual void fromString(std::string & str)
{
std::stringstream ss;
ss << str;
ss >> m_value;
}
/* ... */
};
I've tried setting/unsetting stream flags but it didn't help.
Clarification
The class is a container template with automatic conversion to/from type T. Strings are only one instance of the template, it must also support other types as well. That is why I want to force operator >> to mimic the behavior of std::getline.
As operator >> is not satisfying our requirement when T=string, we can write a specific function for [T=string] case. This may not be the correct solution. But, as a work around have mentioned.
Please correct me if it won't satisfy your requirement.
I have written a sample code as below:
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
template <class T>
class Data
{
T m_value;
public:
void set(const T& val);
T& get();
};
template <class T>
void Data<T>::set(const T& val)
{
stringstream ss;
ss << val;
ss >> m_value;
}
void Data<string>::set(const string& val)
{
m_value = val;
}
template <class T>
T& Data<T>::get()
{
return m_value;
}
int main()
{
Data<int> d;
d.set(10);
cout << d.get() << endl;
Data<float> f;
f.set(10.33);
cout << f.get() << endl;
Data<string> s;
s.set(string("This is problem"));
cout << s.get() << endl;
}
Here is a solution :
std::istream & ReadIntoString (std::istream & istr, std::string & str)
{
std::istreambuf_iterator<char> it(istr), end;
std::copy(it, end, std::inserter(str, str.begin()));
return istr;
}
(Thanks to the original poster in C++ newsgroup)
Where do you want it to stop? If you want to read a whole line you probably need getline function, if you need an entire string stored in the streamstring object your choise is ostringstream::str method.
I'm assuming you're instantiating that template with T = std::string. In that case you could use getline:
getline(ss, m_value, '\0');
However, this assumes you won't accept nul-characters as valid parts of the string.
Otherwise you can write your own extractor for `T'.
There isn't a way with operator>> that I'm aware of excepted writing your own facet (operator>> stop at first character for which isspace(c, getloc()) is true). But there is a getline function in <string> which has the behaviour you want.
If you can use Boost then use boost::lexical_cast.

C++ template specialization question

I'm trying to implement a generic toString() function that would work on all types. All our internal classes derive from Abstract which includes a signature for toString(). In other words, all our internal classes have in some form, a toString method.
The problem is, the primitive types (int, char, double..) don't have a native toString function. But we do have a utility function that calls the lexical_cast to give back the string value of the primitive. We don't want a whole bunch of if statements depending So I'm trying to create a templated utility class that would do the job.
My first hack at this is the below:
template<class T>
class ObjectToString {
public:
string objectToString(T value) {
iil::stringUtils::StringSp ret(stringUtils::valueToString<T>(value));
return ret;
}
};
template<>
class ObjectToString <Abstract<T>*> {
public:
iil::stringUtils::StringSp objectToString(Abstract<T>* value) {
return iil::stringUtils::StringSp(new std::string("AAAA"));
}
};
The problem now is, since Abstract is a templated class, it needs the template value T. I have no idea how to set that. Could anyone advise?
How about simply providing a specialization for lexical_cast?
template<> string lexical_cast(Abstract* obj)
{
return obj->toString();
}
Isn't your problem much simpler? On all Abstract objects you know what to do, so all you need is to provide overloaded functions for built-in types:
string getAsString(Abstract *obj)
{
return obj->toString();
}
string getAsString(int x)
{
return intToStr(x);
}
string getAsString(double x)
{
return doubleToStr(x);
}
etc, where you implement intToStr() and doubleToStr() as appropriate.
This has been dealt with at length by Matthew Wilson in the form of shims, as described in this Dr Dobb's article, and the books Imperfect C++ and Extended STL. They underlie the technology that allow the FastFormat and Pantheios libraries to deal with argument types generically.
You just don't think in C++ way. C++ already has "toString" that is called operator<< to std::ostream. You need to implement it for your classes.
And if you want to support inheritence, do this:
#include <iostream>
#include <boost/lexical_cast.hpp>
#include <string>
class streamable {
public:
virtual void stream(std::ostream &) const = 0;
};
std::ostream &operator<<(std::ostream &out,streamable const &obj)
{
obj.stream(out);
return out;
}
// Now anything derived from streamable can be written to std::ostream
// For example:
class bar : public streamable {
int x;
int y;
public:
bar(int a,int b) : x(a),y(b){}
virtual void stream(std::ostream &out) const { out<<x<<":"<<y; }
};
int main()
{
bar b(1,3);
std::cout<< b << std::endl;
// and converted to string
std::string str=boost::lexical_cast<std::string>(b);
std::cout<< str <<std::endl;
}
This is C++ way, and as you can see you have boost::lexical_cast for free.
EDIT for your case:
template<typename T>
class Abstract {
public:
virtual void stream(std::ostream &) const = 0;
};
template<typename T>
std::ostream &operator<<(std::ostream &out,Abstract<T> const &obj)
{
obj.stream(out);
return out;
}
Now if you don't like boost::lexical_cast, implement string_cast as simple as
template<typename T>
std::string string_cast(T const &obj)
{
std::ostringstram ss;
ss<<obj;
return ss.str();
}

How would I use the >> and << operators for binary data in C++?

Is there a way to use these operators to input and output binary data? The reason I want to do this is that it makes the code readable.
Ex: infile >> filedecrypter >> metadataparser >> audiodecoder >> effects >> soundplayer;
Just to be clear, are you intending to duplicate the semantics of iostreams? Because it looks like you are proposing something different. In the example you give:
infile >> filedecrypter >> metadataparser >> audiodecoder >> effects >> soundplayer;
In iostreams, the meaning here is to read from infile into filedecrypter until you get to whitespace, and then from infile into metadataparser until more whitespace, and so on.
It looks like you are proposing something different, where metadataparser reads from filedecrypter, audiodecoder from metadataparser, etc. In which case I think the answer to your question needs to be qualified a bit.
Can you use operator >> to express this construct? Probably yes.
Can you use iostreams for this? Probably not.
I suggest you clarify what it means when you say A >> B. Perhaps express it as regular methods rather than operator overloads first, and that may clarify the question.
Indeed that can be done, if the library or your code provides the overloads for operator<< and operator>> for it to work. Simple example on how one could do it:
class transformer {
public:
virtual std::iostream& transform(std::iostream&) = 0;
};
class noise : public transformer {
public:
virtual std::iostream& transform(std::iostream&) {
/* extract, change and put into again */
}
};
class echo : public transformer {
public:
virtual std::iostream& transform(std::iostream&) {
/* extract, change and put into again */
}
};
std::iostream& operator>>(std::iostream& io, transformer& ts) {
return ts.transform(io);
}
int main() {
std::stringstream data;
std::ifstream file("sound.wav");
noise n; echo e;
data << file.rdbuf();
data >> n >> e;
/* pipelined data now ready to be played back */
}
The problem with using a pure std::istream is that you would read, but then you wouldn't have a way to put the transformed data back for the next step in the pipeline. Thus i'm using std::iostream here. This approach doesn't seem to be efficient, as every operator>> call would extract the whole data, and put into again.
To have a more performant way to stream this would be to create an expression template. This means, while operator>> is called, you don't do the transforming yet, but you return expression types that will record the chain of operations within its type:
typedef transform< echo< noise< istream > > > pipeline;
std::ifstream file("file.wav");
pipeline pipe(file);
int byte = pipe.get();
would be an example of such a type. The pipelines' structure is decoded into the type itself. Therefore, no virtual functions are needed anymore in the pipeline. It's not constructed on-demand, but using typedef here, to show the principle. Programming such a system is not easy. So you probably should look into existing systems, like Boost.Iostreams (see below). To give you an idea how it would look like, here is an example i just coded up for you :) :
#include <iostream>
template<typename T>
struct transformer {
int get() {
return static_cast<T*>(this)->read();
}
};
struct echot {
template<typename Chain>
struct chain : transformer< chain<Chain> > {
Chain c;
int read() {
return c.get() + 1;
}
chain(Chain const& c):c(c) { }
};
} echo;
struct noiset {
template<typename Chain>
struct chain : transformer< chain<Chain> > {
Chain c;
int read() {
return c.get() * 2;
}
chain(Chain c):c(c) { }
};
} noise;
template<typename T>
typename T::template chain<std::istream&> operator>>(std::istream& is, T) {
return typename T::template chain<std::istream&>(is);
}
template<typename T, typename U>
typename U::template chain<T> operator>>(T t, U u) {
return typename U::template chain<T>(t);
}
int main() {
std::cout << (std::cin >> echo >> noise).get() << std::endl;
}
Entering 0 yields the ASCII code 48 here, which is added 1, and multiplied by 2, yielding a value of 98, which is also finally output. I think you agree this is not some code a starter would want to write. So maybe look into boost.
Boost has an sophisticated iostreams library, which can do many things. I'm sure you would find something fitting to this. Boost.Iostreams
Sure it can be done. Just define your own operator>> and operator<< so they do "the right thing"...
I would make it so I would have methods in the class, like toStream(ostream& os) and fromStream(istream& ), then define
istream& operator>> (istream& is, T& t)
{
t.fromStream(is);
return t;
}
ostream& operator<< (ostream& os, const T& t)
{
t.toStream(os);
return t;
}
There is no need to use streams to move the data. You can create your own classes to do this. This shows an example. Obviously, the Decrypt and MetaDataParser classes can be abstract base classes with virtual functions to allow various functionality be plugged together.
#include <iostream>
#include <istream>
using namespace std;
class Data2
{
};
class Data3
{
};
class Decrypt
{
};
class MetaDataParser
{
};
Data2& operator>>(istream& in, Decrypt& decrypt)
{
return *new Data2;
}
Data3& operator>>(Data2& d2, MetaDataParser& mdp)
{
return *new Data3;
}
int main()
{
Decrypt decrypt;
MetaDataParser mdp;
cin >> decrypt >> mdp;
}