4

I need to make last argument in my function to be a default argument and the type of this argument is *& (reference to pointer). For some reason this doesn't work for me:

template<class T>
void f(T*& = nullptr);  

I'm getting an error:

Error 1 error C2440: 'default argument' : cannot convert from 'nullptr' to 'T *&'

How to get around this?

John Dibling
  • 99,718
  • 31
  • 186
  • 324
There is nothing we can do
  • 23,727
  • 30
  • 106
  • 194

3 Answers3

3

If the argument is optional, it needs to be a pointer, not a reference.

template<class T>
void f(T** const = 0);

If you want the call-style to be pass-by-reference, then you need a forwarder, not a default argument.

template<class T>
void f_impl(T** const);

template<class T>
void f( T*& arg ) { return f_impl(&arg); }

template<class T>
void f( void ) { return f_impl<T>(0); }

If you want to avoid null checks and just discard assignment to the parameter when no parameter is given, do this:

template<class T>
void f(T*&); 

template<class T>
void f( void ) { T* unused = 0; return f(unused); }

Note that T in the no-argument version is a non-deduced context, but so was the original when no parameter was provided.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
1

Basically, if you need to call this function with nullptr (which means "I don't have a value to pass to the function, but want to call it anyway"), then you would want to take the argument per T**.

See How to pass objects to functions in C++? for more on passing arguments.

Community
  • 1
  • 1
sbi
  • 219,715
  • 46
  • 258
  • 445
0

You have an l-value reference to a pointer there, so you'll need to default it to an l-value. Since l-values can't be nullptr (it's an r-value), either you'll need to change the function to take an r-value:

template <typename T>
void f(T const* const& = nullptr)

or, define some l-value pointer for all types T.

template <typename T>
struct NullPtr
{
    static T const* lvalue = nullptr;
};

template <typename T>
void f(T const*& = NullPtr<T>::lvalue)

but I can't imagine any reason you'd actually want an l-value to default to that.

Peter Alexander
  • 53,344
  • 14
  • 119
  • 168
  • Your wrapper is a good syntactic idea, but I am afraid it doesn't add any semantic benefit. There is a reason why non-const references don't bind to rvalues, especially literals, and trying to hack this is pointless :) – Armen Tsirunyan Nov 13 '10 at 19:13
  • @Peter thanks for your answer. Your second example doesn't wont to work for me. I'm getting an error:Error 1 error C2440: 'default argument' : cannot convert from 'Nullptr::value' to 'int *&' – There is nothing we can do Nov 13 '10 at 19:16
  • @Armen: My best guess (assuming he *really* wants an lvalue) is that the parameter is an out parameters, and the default parameter is used when you don't need the out parameters. Here, NullPtr::lvalue acts as a "sink" for the out parameter. – Peter Alexander Nov 13 '10 at 19:19
  • @Peter: Yeah, I thought that too, but came up with a different solution – Armen Tsirunyan Nov 13 '10 at 19:20
  • @Tinwcd: My bad, I'm using g++ 4.5, which doesn't have nullptr so I only tried it with 0 in its place. You probably need const in the type, I'll change this in my answer. – Peter Alexander Nov 13 '10 at 19:22