4

How can I write a constructor specifying default parameters values,

#include <iostream> using namespace std; struct foo { char *_p; int _q; foo( char *p = nullptr, int q = 0 ): _p(p), _q(q) { cout << "_q: " << _q << endl; } }; 

and then use it passing only some values without taking into account their order ?

E.g.: this works:

char tmp; foo f( &tmp ); 

but this doesn't:

foo f( 1 ); $ g++ -O0 -g -Wall -std=c++0x -o test test.cpp test.cpp: In function ‘int main(int, char**)’: test.cpp:18:11: error: invalid conversion from ‘int’ to ‘char*’ [-fpermissive] test.cpp:10:2: error: initializing argument 1 of ‘foo::foo(char*, int)’ [-fpermissive] 

4 Answers 4

2

There is a Named Parameter Idiom. It allows to pass parameters in any order by specifying their names. It also allows to leave some parameters with default values and set only chosen ones in a single statement. Usage example:

File f = OpenFile("foo.txt") .readonly() .createIfNotExist() .appendWhenWriting() .blockSize(1024) .unbuffered() .exclusiveAccess(); 

Idiom description and File implementation details are available at http://www.parashift.com/c++-faq/named-parameter-idiom.html

Sign up to request clarification or add additional context in comments.

1 Comment

Just perfect, most elegant solution by far. Thanks.
2

In a nutshell, you can't ignore the order.

However, you can create more than one constructor.

struct foo { char *_p; int _q; foo( char *p, int q): _p(p), _q(q) {} foo( char *p): _p(p), _q(0) {} foo( int q): _p(nullptr), _q(q) {} }; 

Edit:

By the way, it isn't alway's a good idea to make the order variadic/ignorable. This can sometimes lead to ambiguity or unexpected behavior which is hard to find/debug. In my example calling with NULL parameter leads to ambiguity like here:

class foo { public: foo(int x, unsigned char y=0) : x_(x), y_(y) {} foo(unsigned char x, int y=0) : x_(y), y_(x) {} int x_; char y_; }; 

Just as a hint, use clearly defined constuctors/ function overloads instead.

2 Comments

In his example, a caller using NULL could cause problems, so I wouldn't say it is OK.
Also not a good idea to allow interchanging the order because this leads to a combinatorial explosion of constructors under maintenance.
1

There's no way in C++ to ignore he parameter order. Still, you can just use function overloading and delegating constructors:

struct foo { char *_p; int _q; // this is the default constructor and can also be used for conversion foo( char *p = nullptr, int q = 0 ): _p(p), _q(q) { cout << "_q: " << _q << endl; } // this constructor canbe used for conversion. foo( int q, char *p = nullptr): foo(p, q) {} }; 

Also, consider adding explicit to avoid use of the constructors for implicit conversion.

Comments

0

Order is necessary, based on the order and data type function overloading is working... you can overload the function to achieve you need, like

struct foo { char *_p; int _q; foo( char *p, int q): _p(p), _q(q) {} foo( int q, char *p): _p(p), _q(q) {} foo( char *p):foo(p,0) { } foo( int q):foo(q,nullptr) { } }; 

3 Comments

This does not compile :D but, with a few changes it would work in C++11: foo(char* p): foo(p, 0) {} and foo(int q): foo(q, nullptr) {}
Thank you Massa for pointing out my mistake... i will edit my post
@Massa, that previous version of code was compiling fine in gcc version 4.8.2 , still i have changed as per you suggestion because i fell this is the standard way to do.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.