C++ safe bool wrapper - c++

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

Related

Implementing a custom allocator with fancy pointers

I'm trying to implement my own allocator, which should work with STL containers and use a custom fancy pointer implementation.
I'm pretty sure, that my classes fulfill all requirements (according to cppreference) but my implementation doesn't compile for std::list because there is no conversion from my fancy pointer to a normal pointer.
A minimal example which shows the problem, (but is obviously not my real implementation):
fancy_ptr.h:
#include <cstddef>
template<typename T>
class FancyPtr {
T *ptr;
FancyPtr(T *ptr, bool) : ptr(ptr) {}; //Bool to be non standart
public:
using element_type = T;
FancyPtr(std::nullptr_t n) : FancyPtr() {};
template<class S>
operator FancyPtr<S>() {
return {ptr};
}
T &operator*() { return *ptr; }
T &operator[](size_t n) { return ptr[n]; }
T *operator->() { return ptr; }
bool operator==(const FancyPtr &other) { return ptr == other.ptr; };
static FancyPtr pointer_to(element_type &r) { return FancyPtr(&r, false); };
};
TrivialAllocator.h:
#include "fancy_ptr.h"
template<typename T>
class TrivialAllocator {
public:
using pointer = FancyPtr<T>;
using value_type = T;
TrivialAllocator() = default;
template<typename Other>
TrivialAllocator(const TrivialAllocator<Other> &other) {};
template<typename Other>
TrivialAllocator(TrivialAllocator<Other> &&other) {};
TrivialAllocator(TrivialAllocator &alloc) = default;
pointer allocate(size_t n) { return pointer::pointer_to(*new T[n]); }
void deallocate(pointer ptr, size_t n) { delete[] &*ptr; };
bool operator==(const TrivialAllocator &rhs) const { return true; };
bool operator!=(const TrivialAllocator &rhs) const { return false; };
};
main.cpp:
#include "TrivialAllocator.h"
#include <list>
int main() {
struct Test {};
using AllocT = std::allocator_traits<TrivialAllocator<long double>>;
static_assert(std::is_same_v<FancyPtr<long double>,std::pointer_traits<AllocT::pointer>::pointer>);
static_assert(std::is_same_v<FancyPtr<Test>, std::pointer_traits<AllocT::pointer>::rebind<Test>>);
std::list<long double, AllocT::allocator_type> list;
}
The static assertions are ok.
Can anybody tell me what I have to to to get this working?
PS: I know that operator-> is in something like a conversion operator, but the underlying problem is that std::list seem not to save my fancy pointers, but raw pointers.
Your class does not fulfil all the requirements.
Your pointer type must be a Cpp17RandomAccessIterator (operator++, operator+=, operator+, operator--, operator-, operator-=, operator!=, operator<, operator>=, operator<=)
Your FancyPtr<void> (which would be std::allocator_traits<TrivialAllocator<T>>::void_pointer) does not compile because of the operator[] and pointer_to(void&) (void_pointer and const_void_pointer don't need to be random access iterators)
You can't convert from a pointer to a void_pointer (You need to change your conversion operator to return {static_cast<S*>(ptr);}, or have the static_cast on a constructor of void_pointer)
You can't convert from your pointer type to bool which is one of the requirements for NullablePointer.
Your allocators's allocate and deallocate shouldn't call constructors or destructors.
However, even after making it a valid pointer type for an allocator, you still run into issues with how libstdc++ and libc++ deals with pointers. At some points in the code, there is a cast from FancyPtr<ListNode> to FancyPtr<ListNodeBase>, where ListNode derives from ListNodeBase. This is not part of the requirements of a pointer type, but is used by the implementation of std::list in those standard libraries anyways. You allow this by having operator FancyPtr<T> for any T, which is used. The standard libraries may be able to fix this by converting to a void pointer then to the base class, if the node classes are standard layout.
libstdc++ also internally uses raw T* pointers everywhere, so there are points where it implicitly tries to convert from T* to FancyPtr<T>. Unfortunately, the only way to support this would be to have a public FancyPtr(T*) constructor and a conversion to a raw pointer operator T*(). libstdc++ could fix this without breaking ABI by using p ? std::pointer_traits<pointer>::pointer_to(*p) : pointer(nullptr) to convert a T* p to a fancy pointer, and std::to_address for the reverse.
Microsoft's STL's std::list has no problems with a valid pointer type.
Here is a example implementation of a fancy pointer type that fulfils the requirements and has the workarounds for the 2 standard library implementations mentioned here: https://godbolt.org/z/vq9cvW
After some digging into the problem, I guess this is simply impossible due to libstdc++ internal limitations. This is a known old bug, "Node-based containers don't use allocator's pointer type internally":
Container nodes are linked together by built-in pointers, but they should use the allocator's pointer type instead. Currently I think only std::vector does this correctly. ...
It should work with Clang and libc++ (use -stdlib=libc++ command line option) with a couple of fixes:
FancyPtr<void>::pointer_to(...) should be a valid member function. Now it is not, because void& does not exist.
FancyPtr should provide operator!=(...) member function.
These fixes are needed to make your code at least compilable. Whether it will work correctly is out of scope of this answer.

Is auto(toCast) explicit cast planned in future C++ standard?

I might be completely off-track but ...
while using bunch of explicit conversions from ArrayView to Vector (which I don't want implicit for obvious silent dangerous allocations) such as :
class MyClass
{
void SetInts(ArrayView<int> _view)
{
ints = Vector<int>(_view);
}
Vector<int> ints;
};
I was wondering if such a syntax was planned for future release of C++ (as we already got the auto return which does something quite similar) :
class MyClass
{
void SetInts(ArrayView<int> _view)
{
ints = auto(_view);
}
Vector<int> ints;
};
var = auto(expression) would be a kind of explicit conversion shortcut.
If not, is there some reasons not to write such a thing that I haven't spotted ?
I haven't heard of such proposals.
...But you don't need a new language feature to do that. Something like the following template should work just fine:
#include <utility>
template <typename T>
class auto_cast
{
T &&source;
public:
auto_cast(T &&source) : source(std::forward<T>(source)) {}
auto_cast(const auto_cast &) = delete;
auto_cast &operator=(const auto_cast &) = delete;
template <typename U, typename = decltype(U(std::forward<T>(source)))>
operator U()
{
return U(std::forward<T>(source));
}
};
template <typename T> auto_cast(T &&) -> auto_cast<T>;
Usage: ints = auto_cast(_view);
If not, is there some reasons not to write such a thing that I haven't spotted?
Yes, it's awkward at best and obsfucated at worst.
ints = auto(_view);
it looks like a function call, but using a keyword?
ints = Vector<int>(_view);
here we can see exactly whats happening, construction with possibly eluded copy assignment.

Make explicit when a struct is truthy or falsy in C++

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.

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

How do I make a class in C++, when initialized, return a boolean value when its name is invoked, but no explicit function call make, like ifstream

How do I make a class in C++, when initialized, return a Boolean value when its name is invoked, but no explicit function call make, like ifstream. I want to be able to do this:
objdef anobj();
if(anobj){
//initialize check is true
}else{
//cannot use object right now
}
not just for initialization, but a check for its ability to be used.
The way istream does it is by providing an implicit conversion to void*
http://www.cplusplus.com/reference/iostream/ios/operator_voidpt/
stream output and implicit void* cast operator function invocation
Update In reaction to the comments, the Safe Bool Idiom would be a far better solution to this: (code directly taken from that page)
class Testable {
bool ok_;
typedef void (Testable::*bool_type)() const;
void this_type_does_not_support_comparisons() const {}
public:
explicit Testable(bool b=true):ok_(b) {}
operator bool_type() const {
return ok_==true ?
&Testable::this_type_does_not_support_comparisons : 0;
}
};
template <typename T>
bool operator!=(const Testable& lhs,const T& rhs) {
lhs.this_type_does_not_support_comparisons();
return false;
}
template <typename T>
bool operator==(const Testable& lhs,const T& rhs) {
lhs.this_type_does_not_support_comparisons();
return false;
}
The article by Bjorn Karlsson contains a reusable implementation for the Safe Bool Idiom
Old sample:
For enjoyment, I still show the straight forward implementation with operator void* overloading, for clarity and also to show the problem with that:
#include <iostream>
struct myclass
{
bool m_isOk;
myclass() : m_isOk(true) { }
operator void* () const { return (void*) (m_isOk? 0x1 : 0x0); }
};
myclass instance;
int main()
{
if (instance)
std::cout << "Ok" << std::endl;
// the trouble with this:
delete instance; // no compile error !
return 0;
}
This is best accomplished using the safe bool idiom.
You provide an implicit conversion to a member-function-pointer, which allows instances of the type to be used in conditions but not implicitly convertyed to bool.
You need a (default) constructor and an operator bool()().
class X {
public:
operator bool ()const{
//... return a boolean expression
}
};
usage:
X x; // note: no brackets!
if( x ) {
....
}
You'll want to create an operator bool function (or as boost does, an unspecified_bool_type that has certain improved properties I can't recall offhand). You may also want to create operator! (For some reason I seem to recall iostreams do this too).