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.
Related
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);
}
Let's suppose I want to write my own manipulator for input and output.
cin >> mymanip >> str;
or
cout << mymanip << str;
What I want that mymanip does is toggle case the caracters I read from input and assigns the result to one string.
So, if I type "QwErTy" I get "qWeRtY" in the string.
This is a very basic task with one function, but i want to learn more about manipulators.
Can someone give a clue?
Thank you.
All that a manipulator does is set the corresponding bits in the std::ios_base base class.
For example, the std::setprecision() manipulator simply invokes std::ios_base::precision(), on the manipulated stream.
The implementation of std::setprecision() is almost readable, in gcc's headers (a rarity, for a C++ library template implementation):
inline _Setprecision setprecision(int __n)
{ return { __n }; }
std::setprecision() returns an internal std::_Precision object. Then, a simple template overload for the >> (and the << operator, which is similar) operator, for the std::_Precision object, handles the rest of the magic:
template<typename _CharT, typename _Traits>
inline basic_istream<_CharT, _Traits>&
operator>>(basic_istream<_CharT, _Traits>& __is, _Setprecision __f)
{
__is.precision(__f._M_n);
return __is;
}
In your case, there are no bits in the std::ios_base class that implement your desired input/output transformation. As such, a manipulator, per se, won't work here.
What you're trying to do requires a completely different, more complicated, approach:
A custom subclass of std::[io]stream, that uses a custom subclass of std::streambuf.
The std::streambuf subclass reads or writes from a chained stream, transforming the input or output as you've described.
Reading or writing from the custom subclass ends up reading or writing from the chained stream, transforming the data accordingly.
The way is a little tricky - but it can be done, you can add own manipulator for stream.
First, you need your toggle:
class toggle_t {};
constexpr toggle_t toggle;
Next - the version for ostream (the case for istream is very similar...):
After putting toggle to ostream - you need some special object:
struct toggled_ostream
{
std::ostream& os;
};
inline toggled_ostream operator << (std::ostream& os, toggle_t)
{
return { os };
}
Beware, that someone might put togglein wrong place: cout << toggle << 123 - so it should work for all other types as ordinary stream:
template <typename T>
std::ostream& operator << (toggled_ostream tos, const T& v)
{
return tos.os << v;
}
So - for char types (like char, const char*, std::string) write your toggle overloads. I am giving you version for char - it shouldn't be a problem to write version for "longer" types:
std::ostream& operator << (toggled_ostream tos, char v)
{
char c = std::isupper(v) ? std::tolower(v)
: std::islower(v) ? std::toupper(v) : v;
return tos.os << c;
}
Working demo.
You cannot do that. What you can do instead are manipulators that would take the string as argument, i.e.
std::cout << toggle(str);
std::cin >> toggle(str);
A manipulator is only ever so-called syntactic sugar, i.e. it can do things more conveniently than otherwise. For example,
std::cout << std::setw(5) << x <<;
will do the same as
std::cout.width(5);
std::cout << x;
but is more convenient as it allows to be chained together with other << operations.
Now, there is no formatting support of the thing you want (swap lower and upper case characters), and hence also no way to provide syntactic sugar for that.
However, if the manipulator can take your string as an argument, then of course, you can achieve what you want, implemented in the standard way of manipulator implementation. For example,
struct toggle_output
{ std::string const&str; }
inline toggle_output toggle(std::string const&str)
{ return {str}; }
inline std::ostream& operator<<(std::ostream&out, toggle_output const&t)
{
for(auto c:t.str)
if (std::islower(c)) out<<std::toupper(c);
else if(std::isupper(c)) out<<std::tolower(c);
else out<<c;
return out;
}
struct toggle_input
{ std::string &str; }
inline toggle_input toggle(std::string&str)
{ return {str}; }
inline std::istream& operator>>(std::istream&in, toggle_input &t)
{
in >> t.str;
for(auto&c:t.str)
if (std::islower(c)) c=std::toupper(c);
else if(std::isupper(c)) c=std::tolower(c);
return in;
}
You may also need (to avoid confusion)
inline std::ostream& operator<<(std::ostream&out, toggle_input const&t)
{ return out<<toggle_output(t.str); }
As other answers explain, manipulators simply mimic existing std::ios_base functionality.
There's a simple solution to your problem, though I'm not sure if this can be called a manipulator:
struct toggle_in_helper
{
std::string & res;
};
toggle_in_helper toggle (std::string & res)
{
return {res};
}
std::istream & operator >> (std::istream & in, toggle_in_helper h)
{
in >> h.res;
for (auto & c : h.res)
// toggle the case of 'c'
;
return in;
}
That is, we create a helper class toggle_in_helper with overloaded operator >> which does the job.
I've got a template class derived from std::basic_stringstream<typename TString::value_type...>, as you can see. The problem happens while trying to convert them. It's probably an obvious problem, though I cannot seem to figure out the solution.
As example in main, I have a simple std::wstring and initialize it with L"123".
After the std::wstring has been constructed, the operator of the custom basic_stringstream class is called (depending on std::wstring or std::string).
Inspecting the WCStringStream object for debugging purposes, shows that it contains - instead of the string L"123", the address of the first element of the entered string. The functions to_bytes and from_bytes do return the correct converted string, so the only problem left is the operator being called in both operator-functions:
*this << std::wstring_convert<...>().xx_bytes(s);
Example:
Template class is std::wstring.
Input is a std::string.
&operator<<(const std::string &s) is being called.
String is converted.
&operator<<(const std::wstring &s) is being called.
String-type matches with template type.
Operator of base-class (basic_stringstream) is called. (Or std::operator...)
Result:
Inspecting: {_Stringbuffer={_Seekhigh=0x007f6808 L"003BF76C췍췍췍췍췍췍췍췍췍...}...}
WCStringStream<std::wstring>::str() -> "003BF76C"
Expected result:
"123"
What's going wrong here ?
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <Windows.h>
#include <iostream>
#include <sstream>
#include <codecvt>
template<class TString>
class WCStringStream : public std::basic_stringstream<typename TString::value_type,
std::char_traits<typename TString::value_type>,
std::allocator<typename TString::value_type> >
{
typedef typename TString::value_type CharTraits;
typedef std::basic_stringstream<CharTraits, std::char_traits<CharTraits>, std::allocator<CharTraits> > MyStream;
//more typedefs...
public:
//Constructor...
inline WCStringStream(void) { }
inline WCStringStream(const TString &s) : MyStream(s) { }
//and more...
//operator>> overloads...
//defines for VS2010/2015 (C++11) included
inline WCStringStream &operator<<(const std::wstring &s)
{
if (typeid(TString) == typeid(s))
MyStream::operator<<(s.c_str());
else
*this << std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t>().to_bytes(s);
return *this;
}
inline WCStringStream &operator<<(const std::string &s)
{
if (typeid(TString) == typeid(s))
MyStream::operator<<(s.c_str());
else
*this << std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t>().from_bytes(s);
return *this;
}
};
//Example main
int main(int argc, char *argv[])
{
typedef std::wstring fstring;
WCStringStream<std::wstring> ws;
WCStringStream<std::string> ss;
ws << fstring(L"123");
int a = 0;
ws >> a;
std::cout << a << std::endl;
ss << fstring(L"123");
int b = 0;
ss >> b;
std::cout << b << std::endl;
return 0;
}
I'm compiling currently in VS2015 but I'd need it to run on VS2010 too.
First off: I think the approach to overload formatting function in a base class is ill-advised and I strongly recommend to not do it! I do realize that any alternative will require a bit more work.
In fact, I think your primary problem is actually that you do not reach your overloaded functions anyway just showing how fragile the approach is (I think the string describe what overload ends up being called but I haven't verified that these are indeed accurate, partly because the code provided in the question is lacking necessary context):
WCStringStream<std::string> stream;
stream << "calls std::operator<< (std::ostream&, char const*)\n";
stream << L"calls std::ostream::operator<< (void const*)\n";
stream << std::string("calls std::operator<< (std::ostream&, T&&)\n";
std::string const s("calls your operator\n");
stream << s;
Since the overloaded output operators for strings and string literals can't be changed and they do the wrong think with respect to code conversions, I recommend using an entirely different approach although it still won't be without peril(*): convert the strings explicitly although using a more nicely packaged version of the code than the standard provides.
Assuming always using char as character type for all uses I would use a function wcvt() which is called for all strings and string-literals when inserting them into a stream. Since at the point the function is being called it wouldn't know the type of the stream it is going to be used with, it would return essentially a reference to the character sequence which is then converted appropriately for the character type used for the stream. That would be something along these lines:
template <typename cT>
class wconvert {
cT const* begin_;
cT const* end_;
public:
wconvert(std::basic_string<cT> const& s)
: begin_(s.data())
, end_(s.data() + s.size()) {
}
wconvert(cT const* s)
: begin_(s)
, end_(s + std::char_traits<cT>::length(s)) {
}
cT const* begin() const { return this->begin_; }
cT const* end() const { return this->end_; }
std::streamsize size() const { return this->end_ - this->begin_; }
};
template <typename cT>
wconvert<cT> wcvt(cT const* s) {
return wconvert<cT>(s);
}
template <typename cT>
wconvert<cT> wcvt(std::basic_string<cT> const& s) {
return wconvert<cT>(s);
}
template <typename cT>
std::basic_ostream<cT>& operator<< (std::basic_ostream<cT>& out,
wconvert<cT> const& cvt) {
return out.write(cvt.begin(), cvt.size());
}
std::ostream& operator<< (std::ostream& out, wconvert<wchar_t> const& cvt) {
auto tmp = std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t>().to_bytes(cvt.begin(), cvt.end());
return out.write(tmp.data(), tmp.size());
}
std::wostream& operator<< (std::wostream& out, wconvert<char> const& cvt) {
auto tmp = std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t>().from_bytes(cvt.begin(), cvt.end());
return out.write(tmp.data(), tmp.size());
}
Of course, using this approach requires the use of wcvt(s) whenever s may be a string which needs to be converted. It is easy to forget doing so and it seems the original objective was to not have to remember the use of such a conversion. However, I don't see any alternative which is less fragile with the system of existing streams. Entirely abandoning the use of streams and using an entirely separate system of formatted I/O may yield less fragile approach.
(*) The approach easiest to get right is to stick with just on character type in a program and always using this character type. I do believe it was actually an error to introduce a second character type, wchar_t, and it an even bigger error to further complicate the existing mess by having also introduced char16_t and char32_t. We'd be much better off there were just one character type, char, although it actually wouldn't represent character but bytes of an encoding.
The problem was to explicitly call the base class operator, which takes the const void *_Val overload and prints the address.
MyStream::operator<<(s.c_str());
The solution to the problem:
if (typeid(TString) == typeid(s))
{
MyStream &os = *this;
os << s.c_str();
}
Of course calling *this << s.c_str() results in recursion, but the using the base class, it calls the global overloaded operator for the correct char-type wchar_t / char.
An also working solution is to use the member-function write instead of the operator.
I have a Exception base class which defines a stream function:
class Exception
{
public:
template <typename TData, typename TException>
TException& stream(const TData& data)
{
stream_ << data;
return *reinterpret_cast<TException*>(this);
}
};
I have a free function overloading operator<<:
template <typename TData>
Exception& operator<<(Exception& ex, const TData& data) {
return ex.stream<TData, Exception>(data);
}
I also have dervied exceptions overloading operator<<:
template <typename TData>
CoffeeException& operator<<(CoffeeException& ex, const TData& data) {
return ex.stream<TData, CoffeeException>(data);
}
I use this like so:
else {
throw CoffeeException() << "Exception text";
}
When I try to use the class the compiler doesn't see the function, it just suggests the standard stream operators avaiable but doesn't note my Exception or CoffeeException free functions. Does this implementation look correct?
It looks like the usual problem of trying to bind a temporary to a
non-const reference. CoffeeException() << "Exception text" can't bind
to your operator<<, because CoffeeException() is a temporary. Just
make your operator<< a member:
class CoffeeException : public Exception
{
// ...
public:
template <typename TData>
CoffeeException& operator<<( TData const& data )
{
stream( data );
return *this;
}
};
While I'm at it: you definitely don't want the reinterpret_cast at the
end of Exception::stream. Using the results of this cast is undefined
behavior. It will typically work in cases of single inheritance, but
fail where multiple inheritance is involved (but even that isn't
guaranteed). The simplest solution is what I've done above (and make
Exception::stream return void); alternatively, use static_cast
here (which should be legal if the inheritance is defined at the point
of instantiation).
CoffeeException& operator<<(const CoffeeException& ex, const TData& data);
This reference must be const, because you try pass unnamed object.
You can also create temporary object to avoid using const reference.
There is the complex<> template in C++ standard library, and it has an overloaded << operator so that it outputs complex numbers in the (real_part, im_part) format. I need to change the behavior of that operator for complex numbers so that the output format is changed to something completely different. Specifically, I need the output to be in the form real_part\tim_part. How do I do that?
There's no direct way to replace operator <<, but you do have a few options. First, you could just write your own function to print complex numbers:
template <typename T> void PrintComplex(const complex<T>& c) {
/* ... */
}
If you want to still use the nice stream syntax, then one trick you could do would be to make a wrapper class that wraps a complex and then defines its own operator << that prints it out in a different way. For example:
template <typename T> class ComplexPrinter {
public:
/* Conversion constructor allows for implicit conversions from
* complex<T> to ComplexPrinter<T>.
*/
ComplexPrinter(const complex<T>& value) : c(value) {
// Handled in initializer list
}
/* Output the complex in your own format. */
friend ostream& operator<< (ostream& out, const ComplexPrinter& cp) {
/* ... print in your own format ... */
}
private:
complex<T> c;
};
Once you have this, you could write something like
cout << ComplexPrinter<double>(myComplex) << endl;
You can make this even cleaner by writing a function like this one to wrap the object for you:
template <typename T>
ComplexPrinter<T> wrap(const complex<T>& c) {
return ComplexPrinter<T>(c);
}
This then lets you write
cout << wrap(myComplex) << endl;
Which isn't perfect, but is pretty good.
One thing to note about the above wrapper is that it has an implicit conversion constructor set up to let you convert complex<T>s to ComplexPrinter<T>s. This means that if you have a vector< complex<T> >, you can print it out using your custom code by calling
vector< complex<double> > v = /* ... */
copy (v.begin(), v.end(), ostream_iterator< ComplexPrinter<double> >(cout, " "));
On output, the implicit conversion constructor will transform your complex<double>s into the wrappers, and your custom code will do the printing for you.
If you want to be very adventurous and cast caution to the wind, you could even write the class so that it just stores a reference to the original complex, as shown here:
template <typename T> class ComplexPrinter {
public:
/* Conversion constructor allows for implicit conversions from
* complex<T> to ComplexPrinter<T>.
*/
ComplexPrinter(const complex<T>& value) : c(value) {
// Handled in initializer list
}
/* Output the complex in your own format. */
friend ostream& operator<< (ostream& out, const ComplexPrinter& cp) {
/* ... print in your own format ... */
}
private:
const complex<T>& c;
};
This completely eliminates any copying and just makes the wrapper a thin veneer around a real complex. (No pun intended). You'd have to be very careful if you did this not to pass these objects around across scope boundaries where the original objects go out of scope, but if it's what you want it might work out just great.
Hope this helps!
template<class T>
struct my_complex_format_type {
std::complex<T> const &x;
my_complex_format_type(std::complex<T> const &x) : x (x) {}
friend std::ostream& operator<<(std::ostream &out,
my_complex_format_type const &value)
{
out << "format value.x however you like";
return out;
}
};
template<class T>
my_complex_format_type<T> my_complex_format(std::complex<T> const &x) {
return x;
}
void example() {
std::cout << my_complex_format(some_complex);
}
For any specific instantiation of complex<T>, Use a strong typedef (boost has a version) and cast to that type during << calls. Override << for that type.
If you need to override << for any variation of complex<T> then life will be harder.
My answer to the same question here: c++ display complex number with i in imaginary part produces the behavior you want, at the expense of some risk of future incompatibility because it inserts a template specialization into the std:: namespace.
There is no really tidy way to do that. My suggestion would be to just ditch iostreams and write something more C-like instead. It will probably be faster to write, faster to read and faster to execute.