# variation of the named parameter idiom.

6 replies to this topic

DevMaster Staff

• Members
• 1057 posts

Posted 07 September 2005 - 12:54 PM

Hey guys,

I just thought of experimenting with something today, a little variation on the named parameter idiom. It's a bit bloated, but I'm just messing around a little bit. Anyway, I came across a problem, my first guess is that this might not be allowed by the language in the first place - in which case I can use the boost preprocessor library to make a number of constructors, but I'd prefer that to be the last resort.

The troublesome bit of code is this pices:

struct NullParameter {
NullParameter() {}
void operator () ( void* o ) const
{}
};

class Texture
{
template< class P0 , class P1, class P2, class P3 >
Texture( const P0& p0 = NullParameter(),
const P1& p1 = NullParameter(),
const P2& p2 = NullParameter(),
const P3& p3 = NullParameter() )
: m_width(0),
m_height(0),
m_name(""),
m_useColorKey(false),
m_colorKey(0),
m_colorKeyAlpha(0)
{
p0(this);
p1(this);
p2(this);
p3(this);
// this->create();
}
};


It compiles fine if I privide arguments to all the parameters, but if it's not four, it complains about "does not take 3 arguments". So this would work:

Texture t( Texture::argSize( 500, 600 ),
Texture::argFilename( "happy" ),
Texture::argFormat( Texture::TF_Float32 ),
Texture::argColorKey( 0x0, 0x0 ) );


But this would not:

Texture t( Texture::argSize( 500, 600 ),
Texture::argFilename( "happy" ),
Texture::argFormat( Texture::TF_Float32 ) );


So is there a way to solve this problem without making multiple constructors? Incase you're wondering, Texture::argSize, Texture::argColorKey and the others are structures within the Texture class that overload operator () with a single parameter to a Texture*. The operator () overload is responsible for setting the private variables of the Texture object based on what was passed in at their time of construction: Eg: argColorKey would look like this:

class Texture
{
public:
//====
struct argColorKey {
//====
argColorKey( uint32 c, uint8 a ) : color(c), alpha(a)
{}
void operator () ( Texture* o ) const {
o->m_useColorKey = true;
o->m_colorKey = color;
o->m_colorKeyAlpha = alpha;
}
private:
uint32 color;
uint8 alpha;
};
};


### #2.oisyn

DevMaster Staff

• Moderators
• 1842 posts

Posted 07 September 2005 - 01:33 PM

<s>Your code is fine, what compiler are you using?</s>

.edit: disregard that, looks like the constructor is not considered in the list of possible overloads for some reason... I'll have a look in the C++ spec

.edit2: Hmpff, how stupid of me to forget:
14.8.2.4

Quote

-17- A template type-parameter cannot be deduced from the type of a function default argument. [Example:

template <class T> void f(T = 5, T = 7);
void g()
{
f(1);                   //  OK: call  f<int>(1,7)
f();                    //  error: cannot deduce  T
f<int>();               //  OK: call  f<int>(5,7)
}

About the solution, you could overload the , operator to create a list of 'arguments' to your function (then you're going more in the direction of boost::parameter). The downside of this is that you'll need extra parentheses around your argument list. Or you can use another operator, such as <<, to circumvent that.
-
Currently working on: the 3D engine for Tomb Raider.

### #3bramz

Valued Member

• Members
• 189 posts

Posted 07 September 2005 - 03:26 PM

This is just guessing ... I might be making a fool of myself now :)

I'm trying to "move" the default parameter to the template part ...

class Texture
{
template< class P0 = NullParameter, class P1 = NullParameter, class P2 = NullParameter, class P3 = NullParameter >
Texture( const P0& p0 = P0(),
const P1& p1 = P1(),
const P2& p2 = P2(),
const P3& p3 = P3() )


Bramz
hi, i'm a signature viruz, plz set me as your signature and help me spread :)
Bramz' warehouse | LiAR isn't a raytracer

### #4bramz

Valued Member

• Members
• 189 posts

Posted 07 September 2005 - 03:35 PM

Myself, I use a construct like following for the named parameter idiom:

class Texture
{
class Arg
{
public:
Arg(): width_(0), height_(0), filename_("") {}
Arg& size(int width, int height) { width_ = width; height_ = height_; return *this; }
Arg& filename(const std::string& name) { filename_(name); return *this;
private:
friend class Texture;
int width_;
int height_;
std::string filename_;
};

Texture(const Arg& iArgs):
width_(iArgs.width_),
height_(iArgs.height_),
filename_(iArgs.filename_)
{
}
};

Texture t(Texture::Args().size(256, 256).filename("foo"));


Of course, your problem is how you can do it the other way :)
hi, i'm a signature viruz, plz set me as your signature and help me spread :)
Bramz' warehouse | LiAR isn't a raytracer

### #5.oisyn

DevMaster Staff

• Moderators
• 1842 posts

Posted 07 September 2005 - 04:13 PM

bramz said:

This is just guessing ... I might be making a fool of myself now
Unfortunately, default template arguments are only allowed for class templates, not for function templates :wink:
-
Currently working on: the 3D engine for Tomb Raider.

### #6bramz

Valued Member

• Members
• 189 posts

Posted 07 September 2005 - 04:18 PM

.oisyn said:

bramz said:

This is just guessing ... I might be making a fool of myself now :)
Unfortunately, default template arguments are only allowed for class templates, not for function templates :wink:

bummer :)
hi, i'm a signature viruz, plz set me as your signature and help me spread :)
Bramz' warehouse | LiAR isn't a raytracer

DevMaster Staff

• Members
• 1057 posts

Posted 08 September 2005 - 03:38 AM

well that sucks...

Quote

About the solution, you could overload the , operator to create a list of 'arguments' to your function (then you're going more in the direction of boost::parameter). The downside of this is that you'll need extra parentheses around your argument list. Or you can use another operator, such as <<, to circumvent that.

Yeah those are solutions, another one would be to use the boost.preprocessor library to mechanically generate the different constructor overloads. but anyway, thatnks guys.

#### 1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users