Michael
Michael

Reputation: 7809

nullptr as a template parameter

I have a template like:

template <class A, class B>
void func(A* a, B* b){
  ...
}

In some cases it happens that parameter B* b is not needed and therefore, I try to use a nullptr:

MyA a;
func(&a, nullptr);

The compiler doesn't like that since nullptr somehow is not a type.

How can I deal with that situation? The only idea is to just use a dummy type for that case.

Upvotes: 10

Views: 7374

Answers (4)

Gin&#233;s Hidalgo
Gin&#233;s Hidalgo

Reputation: 817

This is just another hacky way of doing it, but it works:

T* tNullptr = nullptr;
functionWithTemplate(otherArgument1, tNullptr)

Upvotes: 0

jrok
jrok

Reputation: 55395

Besides the overloading as suggested by Benjamin Lindley, another option is conditionaly enabling the function if the types A and B are either a pointer or std::nullptr_t:

#include <type_traits>

template<typename T>
struct is_pointer : std::integral_constant<bool,
                        std::is_pointer<T>::value ||
                        std::is_same<T, std::nullptr_t>::value    
                    >
{};

template <class A, class B>
typename std::enable_if<
   is_pointer<A>::value && is_pointer<B>::value
>::type
func(A a, B b) { }

But sometimes the simplest is the best, so maybe a second overload template<class A> func(A*); will do the job.

Upvotes: 4

amir ramezani
amir ramezani

Reputation: 1

when you want to call that function, you can do the following instead of the other ways:

    func<a, b>(var_a, nullptr);

by doing this, you just pass your template to function and you can have your own type

Upvotes: 0

Benjamin Lindley
Benjamin Lindley

Reputation: 103693

The problem is that nullptr is not actually a pointer, but an object of type nullptr_t. So it cannot match either A* or B*. One option would be to provide an overload to specifically handle nullptr_t.

template<class A>
void func(A* a, nullptr_t)
{
    func(a, (int*)nullptr);
}

If you also want to allow the first argument to be nullptr, you can provide 2 more overloads. One to handle just the first argument, and one to handle both.

template<class B>
void func(nullptr_t, B* b)
{
    func((int*)nullptr, b);
}

void func(nullptr_t, nullptr_t)
{
    func((int*)nullptr, (int*)nullptr);
}

For any more arguments, this approach becomes unfeasible without code generation, as the number of overloads required is an exponential function of the number of arguments. In that case, I would recommend jrok's approach.

Upvotes: 15

Related Questions