Strange bool overloading - c++

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

Related

C++ safe bool wrapper

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; }
};

What is the purpose of operator RestrictedBool in QScopedPointer?

I read through the code for QScopedPointer and came across something that I haven't been able to make sense of.
Here's the pertinent code from QScopedPointer on code.qt.io:
template <typename T, typename Cleanup = QScopedPointerDeleter<T> >
class QScopedPointer
{
typedef T *QScopedPointer:: *RestrictedBool;
public:
...
#if defined(Q_QDOC)
inline operator bool() const
{
return isNull() ? Q_NULLPTR : &QScopedPointer::d;
}
#else
inline operator RestrictedBool() const
{
return isNull() ? Q_NULLPTR : &QScopedPointer::d;
}
#endif
...
inline bool isNull() const
{
return !d;
}
...
protected:
T *d;
I understand the preprocessor definition that makes QDoc think QScopedPointer has an operator bool instead of operator RestrictedBool. What I don't understand it what purpose RestrictedBool serves and how it does it. For example, a simpler implementation is:
inline operator bool() const
{
return !isNull();
}
In short: What's happening here? Why is operator RestrictedBool underhandedly returning the address of d and why does it exist in the first place instead of operator bool?
This is an implementation of the Safe Bool Idiom, explained here.
The naive implementation:
inline operator bool() const
{
return !isNull();
}
returns an rvalue of bool that can be implicitly used for other operations, e.g.
QScopedPointer<Foo> foo(nullptr);
int i = 1;
if (foo < i)
...
is valid code.
Summary: RestrictedBool is a private typedef of a pointer to the type of d. Using it as the return type for an operator means it can be used in an if statement (if (foo)), but cannot be used with other operators.
Note: C++11 allows the use of explicit operator bool, which eliminates the need for the Safe Bool Idiom in C++11 or later code. An implementation for QScopedPointer in C++11 might look like this:
explicit operator bool() const
{
return !isNull();
}
Thank you to tobi303 and Jarod42 for providing the basis for this answer.
Further reading regarding C++11 and the Safe Bool Idiom:
Chris's C++ Thoughts - Contextually converted to bool
Is the safe-bool idiom obsolete in C++11? - SO question
Very explicit operator bool - a writeup specific to QScopedPointer

Getting a value of object for user-defined classes for while, if and for statements

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.

const-correctness and the safe bool idiom

I have another question related to the safe bool idiom:
typedef void (Testable::*bool_type)() const; // const necessary?
void this_type_does_not_support_comparisons() const {} // const necessary?
operator bool_type() const
{
return ok_ ? &Testable::this_type_does_not_support_comparisons : 0;
}
How come the bool_type (the typedef) and this_type_does_not_support_comparisons are const?
Nobody is supposed to actually call the member function through the return pointer anyway, right?
Is const necessary here? Would operator bool_type (the member function) violate const-correctness otherwise?
The "safe bool idiom" is the technical answer to the question "i want a vehicle that is both sports car and tractor, and maybe a boat". The practical answer is not the technical answer…
That said, the problem it solves is just to give a result that is convertible to bool but not to much of anything else (otherwise an instance of the class could be passed as actual argument where e.g. the formal argument was int, say). A data pointer could be convertible to void*. A function pointer isn't, at least formally within the C++ standard (Posix is something else, practice also).
Using a member function pointer protects against accidentally calling the function, given the pointer from the safe bool operator. The const constricts it a bit, but if fate has put someone on the path of making maximum number of silly mistakes, that person might still manage to call the do-nothing function. Instead of the const I think I would just let it have an argument of a private type, where other code cannot provide such an argument, and then it doesn't have to be a silly member function type anymore.
Can look like this:
#include <stdio.h>
class Foo
{
private:
enum PrivateArg {};
typedef void (*SafeBool)( PrivateArg );
static void safeTrue( PrivateArg ) {}
bool state_;
public:
Foo( bool state ): state_( state ) {}
operator SafeBool () const
{ return (state_? &safeTrue : 0); }
};
int main()
{
if( Foo( true ) ) { printf( "true\n" ); }
if( Foo( false ) ) { printf( "false\n" ); } // No output.
//int const x1 = Foo( false ); // No compilado!
//void* const x2 = Foo( false ); // No compilado!
}
Of course, the practical answer is instead something like this:
#include <stdio.h>
class Foo
{
private:
bool isEmpty_;
public:
Foo( bool asInitiallyEmpty )
: isEmpty_( asInitiallyEmpty )
{}
bool isEmpty() const { return isEmpty_; }
};
int main()
{
if( Foo( true ).isEmpty() ) { printf( "true\n" ); }
if( Foo( false ).isEmpty() ) { printf( "false\n" ); } // No output.
//bool const x0 = Foo( false ); // No compilado!
//int const x1 = Foo( false ); // No compilado!
//void* const x2 = Foo( false ); // No compilado!
}
Summary wrt. questions asked:
How come the bool_type (the typedef) and this_type_does_not_support_comparisons are const?
Somebody didn't quite understand what they coded. Or maybe they intended to restrict the ability to call, a little. But then, pretty futile measure.
Nobody is supposed to actually call the member function through the return pointer anyway, right?
Right.
Is const necessary here?
No.
Would operator bool_type (the member function) violate const-correctness otherwise?
No.
Cheers & hth.,
8.3.5/ A cv-qualifier-seq shall only be part of the function type for
a nonstatic member function, the function type to which a pointer to
member refers, or the top-level function type of a function typedef
declaration. The effect of a cv-qualifier-seq in a function declarator
is not the same as adding cv-qualification on top of the function
type, i.e., it does not create a cv-qualified function type.
If I read correctly, you can return a pointer to non const member in a const member function. You just won't be able to call it with a non const object.
A way to forbid the calling is:
private:
struct private_
{
void this_type_does_not_support_comparisons() {}
};
public:
typedef void (private_::*bool_type)() const;
operator bool_type() const
{
return ok_ ? &private_::this_type_does_not_support_comparisons : 0;
}
Pointer to member functions can still be compared for equality. You have to write an operator== and operator!= for Testable::bool_type types which trigger an error. Easier to do with the CRTP form of the safe bool idiom since those operators become templates and thus can have an erroneous body.
Example:
template <typename T>
class safe_bool_concept
{
// Implementation detail of safe bool
protected:
~safe_bool_concept() {}
public:
operator safe_bool() const
{
return static_cast<const T*>(this)->is_null() ? ...;
}
};
struct Foo : safe_bool_concept<Foo>
{
...
private:
friend class safe_bool_concept<Foo>;
bool is_null() const { ... }
};
then you can do (do the same with !=):
template <typename T>
void operator==(const safe_bool_concept<T>& x, const safe_bool_concept<T>&)
{
x.some_private_member(); // invalid, but won't be generated
// unless safe_bool classes are compared
}
This means that the safe bool idiom should be implemented via CRTP if you want to forbid comparisons. Comparisons to zero will still work however.
If you go the non-member function route, you'll have to provide <, >, <= and >= too.

template class and overloading '=='

I'm making some stack, in which I need to uses this kind of comparison in some function. But I got stuck since I don't know how the prototype for this should look like.
I have the following line in a function.
template <class T>
void function1(T i)
{
if(i == 'a')
//do something
}
I wonder know how the overload prototype should look like for it?
EDIT
Dunno if it's worth to mention, anyway this is what I have tried so far
template
bool Stack<T>::operator==(char c) const
{
cout << c << endl; // just some test
}
No need to comment how this function works, as I have not finished it yet. This part will compile, however at the part where I call this function for the first time is in the Stack::push(T i). The compiler will complain that there are no matching function for this.
error: no match for 'operator==' in 'i == '#''
For overloading operators, the name of the function is operator followed by the actual operator, so operator==. It returns bool. I don't know what your arguments should be based on your code. Probably Stack<T>&, and you need two of them to compare if it's a free function, and one to compare to this if it's a member function.
If you have ways to convert to a Stack<T>, then prefer a free function so that you can convert the left-hand-side.
I'm not sure I understand your question. In order for an instantiation of template function function1 to be well-formed, you'll have to provide a operator== which compares a T and (I'll suppose) a char.
Now, you have two options here :
Provide a bool operator==(char) const member function in your type, for example :
struct A {
bool operator==(char) const { /* ... */ }
};
function1(A()); // OK : comparison uses A::operator==(char)
Provide bool operator==(const T &, char) as a free function, for example :
struct A { /* ... */ };
bool operator==(const A &, char) { /* ... */ }
function1(A()); // OK : comparison uses operator==(const A &, char)
So every T in your function1(t) has to implement operator ==;
For example, as a member function
class A
{
public:
bool operator == (char) const;
};
or a non-member operator:
class A
{
public:
friend bool operator == (const A&, char);
};