Equality with an empty (null-like) struct - c++

The answer to the question here addresses initializing a null-reset or zero struct.
How can I check equality though?
say my struct x is defined as follows:
struct MyStruct {
int a;
int b;
};
and the empty struct :
static const struct MyStruct EmptyStruct;
how do I check equality inside a function that takes a reference to a struct of type x?
void myFunction (... , MyStruct &x, ...){
//some code
if (x != EmptyStruct){ // this doesn't work (see error below)
}
//some code
}
The error I get when I try the above:
no match for 'operator!=' in 'x != EmptyStruct'
EDIT: to make it more clear I understand the error message in terms of overloading the != operator for the struct but since an EmptyStruct is a special kind, how can I deal with that?
I guess the point is that a struct of my type with a = 0 and b = 0 is not the same as the EmptyStruct which should represent null-like struct.

You really need to make up your mind whether your MyStruct is a value type or an identity type.
If it's a value type, then you want to define some part of its value as saying that it's empty:
struct MyStruct {
int x;
int y;
bool empty;
};
If it's an identity type, then you want to check for identity:
void myFunction(MyStruct &m) {
if (&m == &EmptyStruct)
// reference to EmptyStruct. Act accordingly.
}
If you need a singular value like your EmptyStruct, you might want to consider passing a (smart) pointer, and comparing to nullptr to determine whether you've received a singular value.
As a general rule, I'd avoid this type of design in general. Identity types are somewhat foreign to most C++ programmers, and singular values create special cases that you're generally better off without.

You need to overload the equality operator, testing every element of the structure.
bool MyClass::operator==(const MyClass &other) const {
... // Compare the values, and return a bool result.
}

Simply overload the operator== (or operator!=). Or (since by default all members of a struct are public), check all elements inside the structures.
Since your talking something about that your struct is "empty" - there's no such thing. When you create an object, the memory for it should be allocated automatically by the constructor. If you want to check if the passed struct is the static EmptyStruct, check the addresses of both.

Since you are taking the object by reference, I assume you want to test if the user actually passed the global EmptyStruct object as a function argument. This can be achieved easily by comparing addresses:
void foo(MyStruct & x)
{
if (&x == &EmptyStruct) { /* ... */ }
}
(This assumes that MyStruct does not overload operator&.)

It sounds like you want to test whether or not x refers to the same object as EmptyStruct, in which case you want to compare addresses:
if (&x != &EmptyStruct)
although this is a rather odd thing to do; it usually makes more sense to use a pointer, with a well-defined null value to represent "no object", if you want a nullable reference-like type.
== and != are used to compare values, not object identities, and have to be overloaded if you want to define them for class types.

Related

Is it safe to reinterpret_cast<const char*> any struct that starts with a char[size] member?

Suppose I have 2 different structs:
struct A {
char a_name[512];
... // A struct data
}
struct B {
char b_name[256];
... // B struct data
}
Given std::string name, I need to check if an object (be it A or B) exists in a container. As both A and B start with a char[size] member which is the name I'm looking for to compare, I tried the following:
// T is a template parameter which is always an object of type A or B
↓
for (const T& item : container)
if (name == reinterpret_cast<const char*>(&item))
It does work as expected. I read the object as if it was an array of chars, but as A.a_name and B.b_name are guaranteed to be null terminated, I don't read what I shouldn't... or do I? Can the code above produce undefined behaviour? Can it produce any error that I'm not taking into account? If so, how can I then approach this task?
I cannot modify A or B. I chose not to overload operator== for each class because A and B are actually many more different structs which have that structure I described above (char[size] + some more data).
Your code should be safe if your classes are standard layout classes.
At the end of the section [class.members], we have
If a standard-layout class object has any non-static data members, its address is the same as the address of its first non-static data member if that member is not a bit-field. ... [Note: The object and its first subobject are pointer-interconvertible]
The section on Compound Types, [basic.compound], says
If two objects are pointer-interconvertible, then they have the same address, and it is possible to obtain a pointer to one from a pointer to the other via a reinterpret_cast.
However, you can get rid of the reinterpret_cast entirely by creating a helper function to return the proper field.
const char *GetName(const A &a) {
return a.a_name;
}
const char *GetName(const B &b) {
return b.b_name;
}
// ...
for (const T& item : container)
if (name == GetName(item))
There are variations on this, including GetName begin a template function that returns a specific field, with specific implementations for types that have a different field name.

Pointer Objects comparison using pointer expression in cpp

I create a two pointer object of a class 'myclass'
myclass *obj1,*obj2;
can I compare these two objects using comparison operator and pointer expression i.e *obj1==*obj2
If yes, how does it happen?
If not, why isn't his allowed?
If yes, how does it happen?
If not, why isn't his allowed?
In short the answer will be yes if you have defined a suitable operator == function for comparing myclass instances and no if you have not defined a suitable operator == function.
There are two ways to declare an operator == function - as a member function of the MyClass class or as a non-member function (sometimes called a global function or free function).
Declaring a MyClass member function might look something like this...
class MyClass
{
public:
bool operator == (const MyClass &rhs) const
{
bool result{ false };
// calculate result;
return result;
}
// ... etc ...
};
Given the statement if (*obj1 == *obj2) the member function above would be called on the *obj1 instance (i.e., this would refer to *obj1) while the *obj2 instance would be passed as the argument to the parameter rhs.
Alternatively, the equality comparison operator for MyClass could be declared as a non-member (aka global) function...
bool operator == (const MyClass &lhs, const MyClass &rhs)
{
bool result{ false };
// calculate result;
return result;
}
In this case, given the statement if (*obj1 == *obj2) the function above would be called with the *obj1 instance passed as the argument to the lhs parameter and the *obj2 instance passed as the argument to the rhs parameter.
You cannot declare both a member function and a non-member function operator == using the same signature. The compiler wouldn't be able to decide which one to call!
Whichever technique you use to declare an operator == function, the "calculate result" code can be absolutely anything that makes sense for your particular class, so long as it returns true or false.
Typically you would compare the various members of the two objects and return true if those members held the same values. But you might not compare all members. Consider, for example, the following Book class...
class Book
{
public:
std::string Title;
std::string Author;
std::string Isbn;
// ... etc ...
};
You might decide that operator == should return true only if the two instances have equal ISBN values because different editions of a book like The Hitchhiker's Guide To The Galaxy should be considered different. Alternatively you might decide that two Book instances are equal if they have the same Title and Author because paperback and hardback editions of the Guide might have different ISBNs but they're still (in some sense) the same book.
Finally(!) it should be noted that while the sample code above uses const MyClass & as the type for the rhs parameter C++ does not require that the rhs parameter be the same type as the lhs parameter.
Normally it would be of course, and defining an operator == function that compared two dissimilar types would be likely to confuse readers and could cause problems for programmers using your class. But, as is often the case, if you think you know what you are doing, C++ won't get in your way.
If you'd like to read more about comparison operators you might find http://en.cppreference.com/w/cpp/language/operator_comparison interesting.
Yes, this will work, but only if you've overloaded the == operator for your class. If you have, then == will invoke the appropriate operator== method, which implements the equality test for your class. In other words, it's up to you to define what equality means for your class.
== operator on pointers will compare their numeric address and hence determine if *obj1 and *obj2 points to the same object or not.
bool operator==(const myclass &obj2); // in this method, see if obj2 is equal to *this.
The code you are suggesting will work only if myclass defines operator==.
And as Jeremy Friesner pointed out, you need to beware of invalid pointers, in particular the value NULL (or nullptr).
So what you really want is:
if ((obj1 != nullptr) && (obj2 != nullptr( && (*obj1 == *obj2)) ...
I would also recommend changing those identifiers to ptr1 and ptr2, as "obj1" and "obj2" would imply to the average reader that they are objects rather than pointers to objects. Or myclsptr1 and myclsptr2, as an indication to the reader of what sort of thing they point to. Or, better yet, names that indicate what their purpose is in this part of the program.
can I compare these two objects using comparison operator and pointer expression i.e *obj1==*obj2
Synactically speaking, you can do that only if the operator is defined for the class. You can do that by overloading the operator== function, which can be a member function or a non-member function.
It will work at run time only if obj1 and obj2 point to valid objects.
If obj1 and obj2 point to valid objects, *obj1 == *obj2 will work just like if you had
MyClass o1;
MyClass o2;
and used o1 == o2
1.Pointer to a class is similar-to pointer to a Structure where if you want to compare you have to access and compare each and every member.
2.You can compare obj1==obj2(which compares address) but if you want to compare two objects *obj1==*obj2 you have to overload "==" operator in your "myclass" like this:::
bool operator==(const myclass& b) {//Compare methods or variables of both objects and return result bool(true/false)

How to implement simple class with variant field in c++

I want to implement class which let's say have field key and class A or B.
The argument in constructor in this class is array of chars.
The constructor pseudocode would take a look at first char, if it is exual to 0x00 it will create class A object,
otherwise it will create class B object - both classes will take the array of chars as argument.
Anyway I want to keep this implementation simple. I don't want to use boost::Variant unless I really need to,
and also I don't want to implement sth like this Implementing a "variant" class
because I am not familiar with template programming and I think my problem can be implemented in much simpler way.
For POD types, we have union (but the union won't remember which type you assigned, so also store this separately). This won't work for non-POD types. The major reason is because C++ doesn't know which one it should create upon construction / delete upon deletion of the union.
But a union can be used to hold pointers to the actual types. Then you have to care about construction and deletion yourself.
You could create something like this, which wraps this pointer-union and adds a convenient interface. Detailed explanation is written in the comments:
class EitherAorB {
// We have to remember what we actually created:
enum Which {
A_Type,
B_Type
} m_which;
// We store either a pointer to an A or to a B. Note that this union only
// stores one pointer which is reused to interpret it as an A*, B* or void*:
union {
A *a;
B *b;
void *untyped; // Accessing the same pointer without looking at the type
} m_ptr;
// Additional stuff you want to store besides A and B
const char *m_key;
public:
EitherAorB(const char *key) {
// Decision: Which type do we want to create?
m_which = key[0] == 0 ? A_Type : B_Type;
// Create the type (the cast to void* make the pointer "untyped"):
m_ptr.untyped = m_which == A_Type ? (void*)new A() : (void*)new B();
// Store additional stuff
m_key = key;
}
~EitherAorB() {
// Since we stored the actual contents outside and point to them,
// we have to free the memory. For this, we have to care about the
// type again, so the correct destructor will be chosen. Deleting
// the untyped pointer won't work here.
if (m_which == A_Type) delete m_ptr.a;
if (m_which == B_Type) delete m_ptr.b;
}
// These two functions can be used to query which type is stored.
bool hasA() const {
return m_which == A_Type;
}
bool hasB() const {
return m_which == B_Type;
}
// These two functions can be used to query the pointers to the actual types.
// I made them return a null pointer if the wrong getter was used.
A *getA() {
return m_which == A_Type ? m_ptr.a : 0;
}
B *getB() {
return m_which == B_Type ? m_ptr.b : 0;
}
}
Note that this implementation will lack memory if you copy an instance of EitherAorB. To fix this, either disable copying (by making the copy constructor and assignment operator private or disable them in C++11 using = delete), or implement the copy constructor and assignment operator which will deeply copy the pointee.
You said you aren't familiar with template programming. Making this implementation templated isn't difficult. Just put template<typename A, typename B> before the whole class definition; it should then work out of the box. However, don't move the implementations in .cpp files in this case; best is to keep them inlined as I wrote it.
Then, A and B aren't types but placeholders you assign types in your client code. I'd then rename the tempalte class to just Either, so your type names become something like Either<This, That>.

Non-owning holder with assignment semantics

I have a class that should hold a reference to some data, without owning that data (i.e. the actual data is guaranteed not to go out of scope). In particular, the class cannot make a copy – the data is easily several gigabytes in size.
Now, the usual implementation (I assume) is to have a reference to the data:
struct holder_ref {
type const& value;
holder_ref(type const& value) : value(value) { }
};
(Please note that the constness has absolutely no bearing on the problem).
Now, I absolutely need this class to be assignable (i.e. have a working operator =). I thought this was a fairly common problem but I can’t remember how (if ever) I’ve solved it before.
The problem is that a reference cannot be assigned and there’s simply no way around this. The only solution I’ve come up with uses placement new in place of the assignment operator:
// x = other_x; gets replaced with:
x.~T();
new (&x) T(other_x);
Now, this works and is standard compliant. But it sure is ugly. No – inacceptable.
So I’m searching for alternatives. One idea is to use pointers, but I’m unsure whether my constructor is actually guaranteed to work (and passing a pointer is impossible due to the interface I have to adhere to):
struct holder_ptr {
type const* value;
// Is this legal?
holder_ptr(type const& value = 0) : value(&value) { }
};
But I’d rather use a reference, if at all possible. Only – how to implement the assignment operator?
struct holder_ref {
type const& value;
holder_ref(type const& value = 0) : value(value) { }
holder_ref& operator =(holder_ref const& other) {
// Now what?!
return *this;
}
};
As a test case, consider the following code:
int main() {
int const TEST1 = 23;
int const TEST2 = 13;
int const TEST3 = 42;
std::vector<holder_ptr> hptr(1);
std::vector<holder_ref> href(2);
// Variant 1. Pointer.
hptr[0] = holder_ptr(TEST1);
// Variant 2. Placement new.
href[0].~holder_ref();
new (&href[0]) holder_ref(TEST2);
// Variant 3. ???
href[1] = holder_ref(TEST3);
assert(*hptr[0].value == TEST1); // Works (?)
assert(href[0].value == TEST2); // Works
assert(href[1].value == TEST3); // BOOM!
}
(Also, just to make this clear – the type we’re talking about is non-POD and I need a standard compliant solution.)
I don't see anything wrong with using a holder_ptr. It can be implemented something like so:
struct bad_holder : std::exception { };
struct holder_ptr {
holder_ptr() : value(0) { }
holder_ptr(type const& value) : value(&value) { }
type const& get() {
if (value == 0) throw bad_holder();
return *value;
}
private:
type const* value;
};
So long as you always assign to the pointer from a reference, you know that you have a valid object (that, or you ended up with a "null reference" previously, in which case you have other, bigger problems since you'll already have invoked undefined behavior).
With this solution, the interface is implemented entirely in terms of references, but under the hood a pointer is used so that the type is assignable. The use of references in the interface ensures there are none of the concerns that come with using pointers (namely, you never have to worry whether the pointer is null).
Edit: I've updated the example to allow for the holder to be default constructible.
I'd use the pointer holder. But if you are dead set against that, how about hiding your placement new operator=:
holder_ref& operator =(holder_ref const& other) {
new (this) holder_ref(other);
return *this;
}
Is a TR1 weak_ptr standard compliant enough?

How to default-initialize local variables of built-in types in C++?

How do I default-initialize a local variable of primitive type in C++? For example if a have a typedef:
typedef unsigned char boolean;//that's Microsoft RPC runtime typedef
I'd like to change the following line:
boolean variable = 0; //initialize to some value to ensure reproduceable behavior
retrieveValue( &variable ); // do actual job
into something that would automagically default-initialize the variable - I don't need to assign a specific value to it, but instead I only need it to be intialized to the same value each time the program runs - the same stuff as with a constructor initializer list where I can have:
struct Struct {
int Value;
Struct() : Value() {}
};
and the Struct::Value will be default-initialized to the same value every time an instance is cinstructed, but I never write the actual value in the code.
How can I get the same behavior for local variables?
You can emulate that behaviour by the following:
boolean x = boolean();
or, more general,
T x = T();
This will default-initialize x if such a default-initialization exists. However, just writing T x will never do the trick for local variables, no matter what you do.
You can also use placement-new to invoke a “constructor”, even for POD:
T x;
new (&x) T();
Notice that this code produces undefined behaviour for non-POD types (in particular for types that have a non-trivial destructor). To make this code work with user-defined types, we first need to call the object’s destructor:
T x;
x.~T();
new (&x) T();
This syntax can also be used for PODs (guaranteed by §§5.2.4/12.4.15) so the above code can be used indiscriminately for any type.
int var = int();
string str = string();
...
...or whatever typename you want.
You could provide a wrapper that behaves as the underlying type through overloaded conversion operators.
#include <cassert>
template <class T>
class Type
{
T t;
public:
Type(const T& t = T()): t(t) {}
operator T&() { return t; }
operator const T&() const { return t; }
};
int main()
{
Type<unsigned char> some_value;
assert(some_value == '\0');
}
This should be a rather OK usage for conversion operators.
Wrapping in the struct (Boolean) as in your example and accessing via a public member (Boolean::value). It may not be the most elegant solution (some cruft for small benefit), but it similar to what you already showed.
If I understand the original question, the poster is saying he wants variables of a given type to always have the same initial value, but he doesn't care what that value is, because he'll never look at it. Am I right?
If so, then my question for the poster is this: If you did not initialize the variables they would have random initial values... but you said you never look at initial values - so why does it matter if they're random?
I think the key question is - what are you trying to achieve here?