MotivationThis is intended to implement a C++ maybe_ptr type that can either hold a pointer to an underlying type T or a nullptr. The idea is to guarantee  at compile-time the absence of null pointer dereferencing errors in code that uses raw pointers. Traditionally, these kinds of errors are prevented by the user having to guard pointer dereferencing by explicitly checking nullptr. For example:void foo(int* n){    if(n != nullptr)    {        bar(*n);    }}The obvious danger is that the user forgets to check for nullptr, in which case it is undefined behavior that is not detected by the compiler and may not even be easily detected at run-time. In contrast, maybe_ptr guarantees nullptr checking before the user is able to deference the raw pointer. UsageBefore getting to the implementation, let's see how maybe_ptr is used (leveraging C++11 lambdas):void foo(const maybe_ptr<int>& ptr){    bool ran = maybe_if(ptr, [](int* n)    {        bar(*n);  // never reached if n is null    });    // ran is true if ptr did not contain null (i.e. the lambda was run)}We can easily assign raw pointers to initialize maybe_ptr:int n;maybe_ptr<int> ptr = &n;Note that maybe_ptr does not allow any direct access to the raw pointer once it is assigned:maybe_ptr<std::string> ptr;std::string* s = *ptr; // compiler error: no * operator definedptr->length(); // compiler error: no -> operator definedptr->get(); // compiler error: get is inaccessible (private method)The only way to access the pointer is through the maybe_if function, with a function pointer, lambda function, or functor. A couple overloaded maybe_if functions are provided for convenient, simultaneous access to multiple pointers within the same lambda function:void foo(const maybe_ptr<int>& ptr1, const maybe_ptr<float>& ptr2){    bool ran = maybe_if(ptr1, ptr2, [](int* n, float* x)    {        bar(*n, *x);  // never reached if n or x are null    });    // ran is true if ptr1 & ptr2 did not contain null}An additional function called maybe_iff is provided, if we want to just throw an exception on nullptr:void foo(const maybe_ptr<int>& ptr){    // throws exception if ptr contains null    maybe_iff(ptr, [](int* n)    {        bar(*n); // never reached if n is null    });}Finally, for additional safety, we also disable the copy constructor in maybe_if (similar to how std::unique_ptr cannot be copied):maybe_if<int> ptr1;maybe_if<int> ptr2 = ptr1;  // compiler error: copy constructor is deletedImplementation#pragma once/// <summary>/// Non-allocating Maybe type for raw pointers. The purpose of maybe_ptr /// is to prevent null pointer dereferencing by wrapping the raw pointer and forcing/// all access to the raw pointer via a functor passed to maybe_if or maybe_iff/// </summary>/// <remarks>/// maybe_ptr does not own the underlying raw pointer (i.e. it does not manage its memory)/// maybe_ptr cannot prevent dangling pointer errors, it only checks for nullptr/// </remarks>/// <typeparam name=T>the underlying type of the raw pointer</typeparam>template <typename T>class maybe_ptr {public:    /// <summary>    /// Construct new maybe_ptr    /// </summary>    maybe_ptr() : _ptr(nullptr), _isNotNull(false) { }    /// <summary>    /// Construct maybe_ptr from a raw pointer. maybe_ptr does not manage the    /// memory of the pointer, it only restricts access to the pointer    /// </summary>    /// <param name=other>raw pointer to wrap with maybe_ptr</param>    maybe_ptr(T* other)    {        set(other);    }    /// <summary>    /// Disable copy constructor to minimize risk dangling pointers    /// </summary>    maybe_ptr(const maybe_ptr&) = delete;    /// <summary>    /// Assignnment operator from raw pointer to this maybe_ptr. Previous raw pointer is overwitten.    /// </summary>    /// <param name=other>raw pointer to wrap with maybe_ptr</param>    /// <returns></returns>    maybe_ptr<T>& operator=(T* other)    {        set(other);        return *this;    }    /// <summary>    /// Bool operator to check if underlying raw pointer is not null    /// </summary>    /// <returns>true if maybe_ptr is not null</returns>    explicit operator bool() const    {        return _isNotNull;    }private:    /// <summary>    /// Return raw pointer    /// </summary>    /// <returns>underlying raw pointer</returns>    T* get() const    {        return _ptr;    }    /// <summary>    /// Set the underlying raw pointer and check if it is null    /// </summary>    /// <param name=ptr>raw pointer to wrap with this maybe_ptr</param>    void set(T* ptr)    {        _ptr = ptr;        _isNotNull = ptr != nullptr;    }    T* _ptr;    bool _isNotNull;    template<typename T, typename FunctorT>     friend bool maybe_if(const maybe_ptr<T>& ptr, typename FunctorT functor);    template<typename T1, typename T2, typename FunctorT>    friend bool maybe_if(const maybe_ptr<T1>& ptr1, const maybe_ptr<T2>& ptr2, typename FunctorT functor);    template<typename T1, typename T2, typename T3, typename FunctorT>    friend bool maybe_if(const maybe_ptr<T1>& ptr1, const maybe_ptr<T2>& ptr2, const maybe_ptr<T3>& ptr3, typename FunctorT functor);    template<typename T, typename FunctorT>    friend void maybe_iff(const T& ptr, typename FunctorT functor);    template<typename T1, typename T2, typename FunctorT>    friend void maybe_iff(const maybe_ptr<T1>& ptr1, const maybe_ptr<T2>& ptr2, typename FunctorT functor);    template<typename T1, typename T2, typename T3, typename FunctorT>    friend void maybe_iff(const maybe_ptr<T1>& ptr1, const maybe_ptr<T2>& ptr2, const maybe_ptr<T3>& ptr3, typename FunctorT functor);};/// <summary>/// Run functor on ptr if ptr is not null, otherwise do nothing /// </summary>/// <param name=ptr>maybe_ptr to run functor on</param>/// <param name=functor>function to if ptr is not null</param>/// <returns>true if functor ran, false if it did not run</returns>template<typename T, typename FunctorT>bool maybe_if(const maybe_ptr<T>& ptr, typename FunctorT functor){    if (ptr)    {        functor(ptr.get());        return true;    }    return false;}template<typename T1, typename T2, typename FunctorT>bool maybe_if(const maybe_ptr<T1>& ptr1, const maybe_ptr<T2>& ptr2, typename FunctorT functor){    if (ptr1 && ptr2)    {        functor(ptr1.get(), ptr2.get());        return true;    }    return false;}template<typename T1, typename T2, typename T3, typename FunctorT>bool maybe_if(const maybe_ptr<T1>& ptr1, const maybe_ptr<T2>& ptr2, const maybe_ptr<T3>& ptr3, typename FunctorT functor){    if (ptr1 && ptr2 && ptr3)    {        functor(ptr1.get(), ptr2.get(), ptr3.get());        return true;    }    return false;}/// <summary>/// Run functor on ptr if ptr is not null, otherwise throw exception/// </summary>/// <param name=ptr>maybe_ptr to run functor on</param>/// <param name=functor>function to if ptr is not null</param>/// <returns>true if functor ran, false if it did not run</returns>template<typename T, typename FunctorT>void maybe_iff(const T& ptr, typename FunctorT functor){    THROW_ASSERT(ptr, Unexpected null maybe_ptr)  // custom assert macro throws exception    functor(ptr.get());}template<typename T1, typename T2, typename FunctorT>void maybe_iff(const maybe_ptr<T1>& ptr1, const maybe_ptr<T2>& ptr2, typename FunctorT functor){    THROW_ASSERT(ptr1 && ptr2, Unexpected null maybe_ptr)    functor(ptr1.get(), ptr2.get());}template<typename T1, typename T2, typename T3, typename FunctorT>void maybe_iff(const maybe_ptr<T1>& ptr1, const maybe_ptr<T2>& ptr2, const maybe_ptr<T3>& ptr3, typename FunctorT functor){    THROW_ASSERT(ptr1 && ptr2 && ptr3, Unexpected null maybe_ptr)    functor(ptr1.get(), ptr2.get(), ptr3.get());}IssuesThe implementation has to explicitly define overloaded versions of maybe_if and maybe_iff for differing numbers of arguments. Currently only overloaded version for one, two or three maybe_ptr arguments are defined. It would be nice to replace this with C++11 variadic templates, but I ran into template argument deduction problems when I attempted to use variadic templates. In a similar vein, it might be nice to eliminate the FunctorT template parameter in maybe_if, and explicitly define the functor argument type as std::function<void(T*)>, std::function<void(T1*, T2*)>, etc., however it appears that C++11 lambdas do not work in that case. The functor seemingly has no way of returning any values. The maybe_if cannot return values from the functor argument (it is assumed to have void return type). The functor also cannot have any additional arguments through which values could be returned. However, this is not a huge deal because we can use lambda capture to assign values to variables in the enclosing scope. The maybe_if usage is more verbose and syntactically awkward that traditional if-statement include guards. The becomes particularly acute when we have to do nested calls to maybe_if.The functions maybe_if and maybe_iff and very similarly named, even though they have very different semantics. An alternative would be to rename maybe_iff to maybe_if_assert or maybe_if_throw but I decided not to do that in order to avoid making the API more verbose than it already is.Use of maybe_if adds the overhead of a conditional branch in every call to maybe_if. The overhead can be amortized over multiple statements by including them within the same call to maybe_if, but the overhead still exists. However, I estimate that it is extremely minimal and worth the added safety.Note: This idea was inspired by a different Maybe type implementation described here (full source)
C++ maybe pointer type implementation
c++;c++11;pointers
Variadic expansionUntil we get fold expressions, we have to use a workaround to check all the pointerstemplate<typename ... Args, typename Func>bool maybe_if(const maybe_ptr<Args> &... args, Func function){  bool result = true;  (void)std::initializer_list<int>{ (result = result && args, 0)... };    if (result)    {      function(args.get()...);    }    return result;}Why return bool (or throw)?The usefulness of an maybe type is more limited when you don't return a maybe<result>. Instead of yourbool ran = maybe_if(ptr, bar);if (ran) {     bar happened, do other stuff    /* why didn't we just if (ptr) { bar(*ptr) } here? */ }Instead it isauto bar_res = maybe_if(ptr, bar);auto baz_res = maybe_if(bar_res, baz);// etc...bool last_res = maybe_if(baz_res, last);return last_res;Doing that would resolve points 3-5, however you are explicitly non-owningDon't use std::functionYour worry that extra overhead will occur from ifs is misplaced, you should be much more worried about hiding functions in std::function<>, which is a very heavyweight construction, which is much more suitable for storing Callables