Ensuring compilation error while passing null pointer to a function

Solution 1:

Is there a way that I can ensure that an error occurs on the compile time whenever nullptr is passed as a parameter.

If you specifically mean the nullptr keyword, then sort of. You can provide overloads that would be chosen in that case, and define them deleted. This works as long as you don't explicitly bypass the overloading by casting for example.

int functionA(int*, std::nullptr_t) = delete;
int functionA(std::nullptr_t, int*) = delete;

// ...
functionA(&i, &j)            // OK
functionA(nullptr, &i);      // error
functionA(&i, nullptr);      // error
functionA(nullptr, nullptr); // error

or NULL

This will require adding overloads for integers in addition to the previous overloads:

int functionA(int*, int) = delete;
int functionA(int, int*) = delete;

// ...
functionA(NULL, &i);      // error
functionA(&i, NULL);      // error
functionA(NULL, NULL);    // error

If you mean any pointer with null value, then that cannot be done because the values of function arguments cannot generally be known at compile time.

If your goal is to not use the pointers as iterators, then it would be safer and more convenient to pass references instead.

Solution 2:

I've somehow managed to find a way to achieve this after a good hour of Google searching. If you really really want to do compile time checking, this is how you can achieve it.

#include <iostream>
#include <cstdlib>

template<typename T, T* N>
static void ValidatePtr() {
    std::static_assert(N != nullptr);
}

int main() {
    constexpr int* ptr = nullptr;
    ValidatePtr<int, ptr>();

    std::cout << "Test" << std::endl;
}

Quick rundown: If you need to validate compile-time pointers for functions, you're going to have to make sure they're constant expressions. The method will actually require a constant expression to even compile. This ensures that the only pointers passed will have to be determined at compile time. You cannot reference the address of other variables using &variable as it will throw compiler errors, so it has to be specifically typed out like constexpr int* ptr = nullptr; or constexpr int* ptr = (int*)0xFFFFFFFF.

However, if you are wanting dynamic variables to be checked, you need to check at runtime since there is no way without using constexpr to determine what the address will be.

I don't really see a use of this outside of maybe a memory utility.

I heavily just recommend having a runtime check for a nullptr and if you feel it is necessary, use a normal assert call instead of a static_assert or simply raise an exception using throw.

Solution 3:

The correct thing to do here is use references.

int functionA(int& a, int& b);

The mental model to have about references is: these are pointers that should never represent nullptr.