Search code examples
c++templatesc++-conceptsnullptr

How to get a typed nullptr "literal"?


I just found out that std::is_pointer_v<nullptr> translates to false, thats why the code below:

template <typename T> std::string_view type_str() { /* returns the name of the type */ }
template <typename T> const auto type_name = type_str<T>();

template <typename T> void fptr(const T *const t) {
    if (t)
        std::print("{} = {:X}.\n", static_cast<const void *const>(t), *t);
    else
        std::print("nullptr.\n");
}
// #1
template <typename T> requires std::is_pointer_v<T> void f(T t) {
    std::print("[{}] is pointer --> ", type_name<T>);
    fptr(t);
}
// #2
template <typename T> void f(T t) {
    std::print("[{}] is NOT pointer.\n", type_name<T>);
}

int main()
{
    const auto v0 = 0xfabada;
    auto v1 = 0xc0ffee;

    f(&v0);
    f(&v1);
    f(nullptr);

    return 0;
}

Yields the following output:

[const int*] is pointer --> 0xWHATEVER = FABADA.
[int*] is pointer --> 0xWHATEVER = C0FFEE.
[std::nullptr_t] is NOT pointer.

I was expecting std::is_pointer_v<std::nullptr_t> to yield true thus calling the #1 function, the only workaround that I've vound so far is to create a kind of typed nullptr:

template <typename T>
constexpr T *NULLPTR = nullptr;

    …

    f(&v0);
    f(&v1);
    f(nullptr);
    f(NULLPTR<int>);

    …

Which prints:

[const int*] is pointer --> 0xWHATEVER = FABADA.
[int*] is pointer --> 0xWHATEVER = C0FFEE.
[std::nullptr_t] is NOT pointer.
[int*] is pointer --> nullptr.

But I wonder if there is any other way to get a nullptr which results in std::is_pointer_v being true without creating a (template variable) pointer instance which may come with potential missuses. Carrying the pointer type information is a plus.


Sample code here.


Solution

  • But I wonder if there is any other way to get a nullptr which results in std::is_pointer_v being true without creating a (template variable) pointer instance which may come with potential missuses. Carrying the pointer type information is a plus.

    Yes there is. Just provide overload of function f which will handle nullptr case. You do not need any extra template just add simple function:

    void f(std::nullptr_t)
    {
        std::print("[{}] is nullptr.\n", type_name<std::nullptr_t>);
    }
    

    https://godbolt.org/z/v5njh9fco