|
Do you have the answer then?
Use the best guess
|
|
|
|
|
Nope. It still doesnt make sense, even after reading it 10 times.
|
|
|
|
|
So this thread was totally pointless.
Use the best guess
|
|
|
|
|
It was, but it was pointless in the right forum.
|
|
|
|
|
I don't think so; read the question again.
Use the best guess
|
|
|
|
|
User error - I missed the additional option to derive the class from any MFC class.
|
|
|
|
|
I am practicing c++ template programming and got a very confusing question. My purpose is to write a program to output the data of classes. If the the class is an POD (plain old data), use a global function (say Serialize) for output, if it's not, use the class's own Serialize function (assume every non-pod class in this program has implemented its own Serialize method). To better illustrate this idea, I have a little program to do that:
#include <assert.h>
#include <iostream>
using namespace std;
class myclass
{
public:
myclass(void):_nID(10) { _nOldID = _nID; };
void Serialize(std::ostream &os)
{
os << _nID;
}
void Serialize(std::istream &is)
{
is >> _nOldID;
}
private:
int _nID, _nOldID;
};
template <typename T>
void Serialize(std::ostream &os, const T& Obj)
{
os << Obj;
}
int main(int argc, char* argv[])
{
typedef unsigned int T;
T Obj;
if (!std::is_pod<T>::value) {
std::cout << "T != POD";
Obj.Serialize(cout); }
else {
Serialize(cout, Obj); std::cout << "T = POD";
}
return 0;
}
The problem is that the compiler giving an error that error C2228: left of '.Serialize' must have class/struct/union in the if clause, which I think it shouldn't because T is defined as unsigned int which is of POD type. On the other hand, if T is defined as myclass, the compiler complains the global Serialize function saying "binary '<<' : no operator found which takes a right-hand operand of type 'const T' (or there is no acceptable conversion)", which is in the "else" clause which should not be reached.
Anybody can explain this?
|
|
|
|
|
You want to do this if I'm right: You want to generate a call to the Serialize() method of the object if the method is implemented in the object otherwise you want to call a fallback method or maybe you want to generate a compile time error. Then you are looking for SFINAE[^]. The solution I provided is much simpler than the one found on the wiki page but I made use of C++11.
#include <assert.h>
#include <iostream>
using namespace std;
class myclass
{
public:
myclass():_nID(10) { _nOldID = _nID; };
void Serialize(std::ostream &os)
{
os << _nID;
}
void Deserialize(std::istream &is)
{
is >> _nOldID;
}
private:
int _nID, _nOldID;
};
class otherclass
{
};
namespace Serialize_SFINAE
{
template <typename T>
auto Serialize(T& obj, std::ostream &os) -> decltype(obj.Serialize(os),void())
{
obj.Serialize(os);
}
template <typename T>
void Serialize(T& obj, ...)
{
obj.this_class_doesnt_have_a_serialize_method;
}
}
template <typename T>
void Serialize(std::ostream &os, T& obj)
{
Serialize_SFINAE::Serialize(obj, os);
}
void Serialize(std::ostream &os, int obj)
{
os << obj;
}
void Serialize(std::ostream &os, bool obj)
{
os << obj;
}
int test_code()
{
myclass Obj;
Serialize(cout, Obj);
return 0;
}
|
|
|
|
|
Thanks for the code and explanation. That's exactly what I intended to do. Your codes get compiled and worked fine.
One more question: If for any class/struct object without Serialize method implemented, I want to use the default serialization for them such as os << Obj or call the global Serialize template function. I just cant use a specialization method for every such class because I can possibly have many such classes.
modified 14-Aug-13 10:30am.
|
|
|
|
|
The fallback sfinae method (void Serialize(T& obj, ...)) is for that case. You can put there a compile error (I did that) but you can put there a default handler code too as an alternative for the case when the struct/class doesn't have a Serialize() method.
I almost forget to mention: When you have to handle primitive types (int, bool, ...) and structs/classes together then it can usually be done by calling an overloaded function/method that has overloads for the primitive types and a template method for the rest (structs/classes). In the template method you can do different kind of magic with the type it is called with, you can call one of its methods, sfinae,... When creating the overload for primitive types there is one strange thing to be aware of: char, signed char, and unsigned char are 3 different types and you need 3 overloads!
|
|
|
|
|
I did learn a lot from what you have explained. Thanks again for your help and patience.
For POD type of data, I used a std::is_class<> predicate to handle and I only need two specializations.
Within your namespace Serialize_SFINAE {...}, I just cannot simply add a default Serialize function which compiler will complain an ambiguous call. Could you be more specific?
|
|
|
|
|
You are welcome!
But I can not be more specific because I don't know what you wanna do from what you described. I never said "adding a new method" in my previous posts to create the "ambiuous call" condition.
|
|
|
|
|
Ok, to be more specific, I have redefined the otherclass to enable it has an << operator:
class otherclass
{
public:
otherclass(void):i(0) {}
friend std::ostream & operator << (std::ostream & os, otherclass &Obj)
{
os << Obj.i;
return (os);
}
int i;
};
In the Serialize_SFINAE name space, I modified it to handle the otherclass serialization:
namespace Serialize_SFINAE
{
template <typename T>
auto Serialize(T& obj, std::ostream &os) -> decltype(obj.Serialize(os),void())
{
obj.Serialize(os);
}
template <typename T>
void Serialize( T& obj, std::ostream &os, ...)
{
os << obj;
}
}
So now the program can handle the otherclassserialization. However, when switch back to myclass, compiler generate an ambiguous call message: error C2668: 'Serialize_SFINAE::Serialize' : ambiguous call to overloaded function
So what should the second Serialize(..) within that name space be in order to handle the object without Serialize internally implemented?
|
|
|
|
|
Well, you actually changed the signature of the Serialize method. You are not allowed to do that. If you want to be able to access a stream for this purpose then put both of these methods into a class instead, store a stream reference/pointer in the class, create an instance of that class and call these sfinae methods of the instance. This way you don't have to change the signature of the sfinae methods. A simpler less nice alternative is not changing the methods but accessing the stream from a global variable.
|
|
|
|
|
Good. That's clarify what I thought and is what I planed to do after the last post.
Thanks again for your kind explanations.
|
|
|
|
|
|
|
|
Good afternoon.
Quote: how can i improve my c programming in different ways?
Coding. Reading good books. Coding. Coding. (did I say 'coding'?).
Veni, vidi, vici.
|
|
|
|
|
Someone on these forums told me that there is a difference in quality between a coder and a programmer. I wish OP to become a programmer, a software engineer. Programming. Programming. Software engineering. Software engineering. Design. Design.
I see the point of OP, he is probably searching for motivators but the first thing to write as a beginner programmer is not a monumental masterpiece and usually not even useful application. Becoming able to write something monumental and/or useful (like a compiler, an operating system kernel, a serious game) requires years of experience - the way is quite long and many "wannabe" programmers don't realize that this can be achieved only by enjoying the way. Many starters give up and some of them reach only the level of a bad programmer usually without satisfactory software design knowledge.
|
|
|
|
|
Back in the early years of my programming career I started with asm programming. I still remember how happy I was when I first put together a "for loop" in an assembly program (at home, I wasn't forced by teachers). It was something that read in some input from the keyboard and then printed it the the screen when the enter key was pressed or something similarly stupid stuff. In assembly even this simple program was a challenge for me despite the fact that it was only a stupid for loop (I didn't even knew that it was a for loop, I only knew that I require a few jumps and condition checking). You have to search for a challange that keeps you motivated but isn't too far beyond what you can achieve with your current knowledge. If that knowledge is zero then the first step is reading books and the code of others'. Don't try to skip reading 1-2 books on C programming, you will regret it and you will waste a lot of time by progressing with much slower speed by doing nothing because of being able to do nothing without the necessary basic knowledge. I can easily imagine that you think your biggest problem is the C programming language itself but you should quickly realize that the language itself is only a tool and the real value is the experience you gain by solving problems. Every language of the same paradigm contains the same basic constructs (loops, functions, classes, ...). The sooner you get through the learning of your first language (for example C) the sooner you can start with solving real-world problems and gaining experience in software design that is much more important than being able to produce compilable lines of code in a language. Without experience even the smallest problems seem to be unsolvable, it requires 1-2 years spent with valuable programming to learn the basic patterns (for example how to read in data and parse it, how to manage memory, ...) in order to be able to handle these naturally without effort by concentrating your efforts on solving the real problems built on top of the simple patterns.
|
|
|
|
|
Uh oh, its the pastapizza daily novel!
Hey, did you ever hear what paragraphs are? Try using them occasionally.
--edit--
I see a sense of humour is lacking in some.
modified 21-Aug-13 10:57am.
|
|
|
|
|
(but scaring at first sight )
Veni, vidi, vici.
|
|
|
|
|
I'm good at writing scaring paragraphs. I have always been terrible in literature, grammar and similar things...
|
|
|
|
|
No no no no no!
It doesnt go 'Good Evening' it goes 'Hello World!'
Dear oh dear, how are you ever going to learn if you dont get this right!
|
|
|
|