I have defined a simple struct mystruct in C++. I would like to be able to use
mystruct a;
// do things to a
if(a) {
/* do things */
}
directly. Is there a way for me to define the behavior of this?
Is there a way for me to define the behavior of this?
Yes, provide an overload for the bool type conversion operator:
class mystruct {
public:
explicit operator bool () const {return condition; } // This is the conversion operator
};
This answer contains some more detailed info.
Related
I'm trying to design a bool wrapper struct applying the safe bool idiom.
The classic implementation to solve this is pretty trivial: the skeleton could be something like this:
struct Bool final
{
Bool() = default;
Bool(bool value)
: _value{value}
{}
explicit operator bool() const {
return _value;
}
private:
bool _value{false};
};
The part I'm trying to improve is how Bool is constructed.
For example I want to avoid implicit narrowing by design:
Bool b1(45); // yields warnings, but it compiles
Bool b2{3}; // not ok by standard
I tried to hurt myself using templates, but without success.
How could I make it work?
You can achieve this by explicitly deleting all other constructors.
struct Bool final
{
template<class T>
Bool(T) = delete;
Bool(bool value);
};
Add, and explicitly delete a template constructor:
template <typename T>
Bool(T) = delete;
It matches anything other than actual bool better than other constructors, and will thus prevent implicit conversion.
If you just need:
A variable that is only "true" or "false" and cannot be implicitly converted to int/char/pointer then I would look at using an enum class:
enum class Bool {
False,
True,
};
I'm trying to design a bool wrapper struct applying the safe bool idiom.
Don't.
The safe bool idiom is only relevant in C++03 and earlier - where if you express that your type is "truthy" by doing something like:
struct A {
operator bool() const;
};
you'd run into all sorts of issues like:
A{} + 4; // ok?!
A{} < 0; // ok?!
A{} == B{}; // ok if B also has operator bool??!
So the safe bool idiom was a solution to this accidental implicit conversion problem, using function pointers (of course, function pointers!).
In C++11, we have a way better solution:
struct A {
explicit operator bool() const;
};
which does exactly what we want. In fact, it was literally designed to solve this problem. And while the safe bool idiom is fairly complicated scaffolding, explicit operator bool is super straightforward to use and just does the Right Thing. You don't need a wrapper for it - it's actually harder to use your wrapper than to write the explicit operator bool directly.
Moreover, your wrapper imposes on the user (a) non-derivability because you made Bool final and (b) an extra bool member, that you have to keep in sync, so it introduces rather than solves problems. Consider how much more work it would be for you to implement:
template <class T>
struct my_unique_ptr : Bool { ... };
vs
template <class T>
struct my_unique_ptr {
T* ptr;
explicit operator bool() const { return ptr; }
};
I've created a class with an enum defined in it. I also wanted to define some operators for the enum like this:
class MyClass
{
public:
enum MyEnum { CONSTA, CONSTB, CONSTC };
// ...
MyEnum& operator++(MyEnum& orig);
MyEnum operator++(MyEnum& orig, int);
// ...
}
For this code, gcc gives the following error message:
.../MyClass.h|10|error: postfix ‘MyClass::MyEnum& MyClass::operator++(MyClass::MyEnum&)’ must take ‘int’ as its argument
.../MyClass.h|11|error: ‘MyClass::MyEnum MyClass::operator++(MyClass::MyEnum&, int)’ must take either zero or one argument
Which means, that the compiler believes that I want to write an operator for MyClass, not for MyEnum. So it wants me to reduce the arguments.
My question is:
Can a class in some way contain operator functions for something else than itself (e.g. for an inner type) or should I move those functions outside of MyClass?
You can use global operator overloads to do this
class MyClass
{
public:
enum MyEnum { CONSTA, CONSTB, CONSTC };
};
MyClass::MyEnum& operator++(MyClass::MyEnum& orig) { return ++orig; }
MyClass::MyEnum operator++(MyClass::MyEnum& orig, int)
{ MyClass::MyEnum temp = orig++; return temp; }
See the compilable code here please.
I am trying to get a bool value out of user defined object.
For example with float or int I can do something like
float a = 3.5
if (a) doSomething();
I want my class to look like this:
class Socket {
...
...
};
...
Socket T;
if (!T) cout << "Error occured";
else {
doStuff();
}
Of course I can define a function that returns bool (like bool isValid();) and call it directly, but I would like to know if it is possible.
In C++11, you can safely convert your type to a boolean value:
explicit operator bool() const {return isValid();}
If your compiler doesn't support that, then you could write the same thing without explicit; however, that can be a bit dangerous because it enables implicit conversions to any numeric type. Instead, you could use a hack known as the safe bool idiom:
private:
typedef void (Socket::*safe_bool)() const;
void safe_true() const {}
public:
operator safe_bool() const {return isValid() ? &Socket::safe_true : 0;}
This returns a pointer type which can't be converted into anything except bool.
Can you explain for me what the typedef here is doing and what the purpose is?
class C
{
public:
...
typedef bool (C::*implementation_defined_bool_type)(bool) const;
operator implementation_defined_bool_type() const {
return _spi ? &C::isPersistent : 0;
}
};
Can you explain for me what the typedef is doing here?
typedef bool (C::*implementation_defined_bool_type)(bool) const;
typedefs a pointer to a const member function of a type C, which takes a bool as input parameter and also returns a bool.
While,
operator implementation_defined_bool_type() const
Takes in an object of type C and returns a type implementation_defined_bool_type.
It is known as an Conversion Operator.
what is the purpose of it?
It implements the "Safe Bool Idiom", which aims to validate an object in a boolean context.
Note that the Safe Bool Idiom is obsolete with the C++11 Standard.
Good Read:
The Safe Bool Idiom
Is there a trick to get the safe bool idiom completely working without having to derive from a class that does the actual implementation?
With 'completely working', I mean the class having an operator allowing it to be tested as if it were a boolean but in a safe way:
MyTestableClass a;
MyOtherTestableClass b;
//this has to work
if( a );
if( b );
//this must not compile
if( a == b );
if( a < b );
int i = a;
i += b;
when using this implementation for example
struct safe_bool_thing
{
int b;
};
typedef int safe_bool_thing::* bool_type;
safe_bool( const bool b ) { return b ? &safe_bool_thing::b : 0; }
class MyTestableClass
{
operator bool_type () const { return safe_bool( someCondition ); }
}
it's almost fine, except a == b will still compile, since member pointers can be compared. The same implementation as above, but with pointer to member function instead of pointer to member variable has exactly the same problem.
Known implementations that do work perfectly (as described here for example, or the safe_bool used in boost) require that the testable class derive from a class providing the actual operator implementation.
I actually think there is no way around it, but'm not entirely sure. I tried something that looked a bit fischy but I thought it might work, yet is doesn't compile at all. Why is the compiler not allowed to see that the operator returns a safe_bool_thing, which in turn can be converted to bool() and hence be tested?
struct safe_bool_thing
{
explicit safe_bool_thing( const bool bVal ) : b( bVal ) {}
operator bool () const { return b; }
private:
const bool b;
safe_bool_thing& operator = ( const safe_bool_thing& );
bool operator == ( const safe_bool_thing& );
bool operator != ( const safe_bool_thing& );
};
class MyTestableClass
{
operator safe_bool_thing () const { return safe_bool_thing( someCondition ); }
};
MyTestableClass a;
if( a ); //conditional expression of type 'MyTestableClass' is illegal
This should work:
class MyTestableClass
{
private:
void non_comparable_type() {}
public:
typedef void (MyTestableClass::* bool_type)();
operator bool_type () const { return (someCondition ? &MyTestableClass::non_comparable_type : 0); }
};
class MyOtherTestableClass
{
private:
void non_comparable_type() {}
public:
typedef void (MyOtherTestableClass::* bool_type)();
operator bool_type () const { return (someCondition ? &MyOtherTestableClass::non_comparable_type : 0); }
};
For blocking the if (a == b) case, it depends on the fact that both types convert to incompatible pointer types.
"Why is the compiler not allowed to see"
I don't have an answer for safe bool, but I can do this bit. It's because a conversion sequence can include at most 1 user-defined conversion (13.3.3.1.2).
As for why that is - I think someone decided that it would be too hard to figure out implicit conversions if they could have arbitrarily many user-defined conversions. The difficulty it introduces is that you can't write a class with a conversion, that "behaves like built-in types". If you write a class which, used idiomatically, "spends" the one user-defined conversion, then users of that class don't have it to "spend".
Not that you could exactly match the conversion behaviour of built-in types anyway, since in general there's no way to specify the rank of your conversion to match the rank of the conversion of the type you're imitating.
Edit: A slight modification of your first version:
#define someCondition true
struct safe_bool_thing
{
int b;
};
typedef int safe_bool_thing::* bool_type;
bool_type safe_bool( const bool b ) { return b ? &safe_bool_thing::b : 0; }
class MyTestableClass
{
public:
operator bool_type () const { return safe_bool( someCondition ); }
private:
bool operator==(const MyTestableClass &rhs);
bool operator!=(const MyTestableClass &rhs);
};
int main() {
MyTestableClass a;
MyTestableClass b;
a == b;
}
a == b will not compile, because function overload resolution ignores accessibility. Accessibility is only tested once the correct function is chosen. In this case the correct function is MyTestableClass::operator==(const MyTestableClass &), which is private.
Inside the class, a == b should compile but not link.
I'm not sure if == and != are all the operators you need to overload, though, is there anything else you can do with a pointer to data member? This could get bloated. It's no better really than Bart's answer, I just mention it because your first attempt was close to working.
EDIT: Oh! I did not read your requirements correctly, so the below does not satisfy all of them.
It is easy enough without any special base class:
struct MyClass
{
int some_function () const;
typedef int (MyClass:: * unspec_bool_type) () const;
operator unspec_bool_type () const
{
return some_condition ? &MyClass::some_function : 0;
}
};
So, given suitable member variable of member function, you can impement it in just 5 lines of simple code.