function pointers with default parameters - change from gcc 3.4.4to 4.5.0?

L

Lars Uffmann

I am trying to add some objects to a collection, handled by a custom
wrapper class called configuration.

I want the wrapper class to behave user friendly, in a way that
configuration.add (key, object);
will add the object if key does not yet exist, or update the object with
new settings if the key already exists in the collection.

I had this working previously, with gcc 3.4.4. and code like this:

--- snip ---
void (configuration::*add_or_set)(string, configParameter, bool =
PARAM_KEEP_CATEGORY);

if (parameters.find(param) == parameters.end()) add_or_set =
&configuration::add;
else add_or_set = &configuration::set;
--- snip ---

Here, "param" reflects the key and "configParameter" is the object. I
would then call add_or_set (param, object) later in the function, to
either insert a new object, or replace the old one's data.

This compiled and linked without warnings, and executed just fine.

However, I just tried this on gcc 4.5.0, and I am getting the error
message at compile time that:
"error: default arguments are only permitted for function parameters"

Does this mean I was using a non standard but supported functionality
which has now been removed? Is there any other way of declaring my
function pointer so that I can call it with only the parameters that
change on every call?

Both underlying functions - add and set - have the exact same parameters
(designed to have identical interfaces), and the default value for the
third (bool) parameter is declared in both function headers.

Best Regards,

Lars
 
A

Alf P. Steinbach

* Lars Uffmann, on 16.06.2010 14:05:
I am trying to add some objects to a collection, handled by a custom
wrapper class called configuration.

I want the wrapper class to behave user friendly, in a way that
configuration.add (key, object);
will add the object if key does not yet exist, or update the object with
new settings if the key already exists in the collection.

I had this working previously, with gcc 3.4.4. and code like this:

--- snip ---
void (configuration::*add_or_set)(string, configParameter, bool =
PARAM_KEEP_CATEGORY);

Raw member pointers do not honor the usual access rules and are therefore best
avoided.

Where you need something like a member pointer (usually you don't, and in
particular here you don't) the basic technique is an object supporting a known
interface.

Where even that isn't flexible enough you can use e.g. a boost::function.

A raw member pointer is like a 'goto'.

There *are* valid cases, but the presence of a raw member pointer in ordinary
code is a red flag, it says, uh oh.

if (parameters.find(param) == parameters.end()) add_or_set =
&configuration::add;
else add_or_set = &configuration::set;
--- snip ---

Here, "param" reflects the key and "configParameter" is the object. I
would then call add_or_set (param, object) later in the function, to
either insert a new object, or replace the old one's data.

With a std::map you can simply do

configuration[key] = value;

This compiled and linked without warnings, and executed just fine.

However, I just tried this on gcc 4.5.0, and I am getting the error
message at compile time that:
"error: default arguments are only permitted for function parameters"

Does this mean I was using a non standard but supported functionality
which has now been removed?

I'm not sure but I think so, yes.

Is there any other way of declaring my
function pointer so that I can call it with only the parameters that
change on every call?

Use a std::map, forget about using 'goto' :).

E.g. wrap your configParameter in a class, whose instances will be values in the
map.

But see above for some less easy solutions (might be worth knowing about for
some later occasion).

Both underlying functions - add and set - have the exact same parameters
(designed to have identical interfaces), and the default value for the
third (bool) parameter is declared in both function headers.


Cheers & hth.,

- Alf
 
L

Lars Uffmann

Alf said:
A raw member pointer is like a 'goto'.

I must admit I didn't look at it that way before. Now that you mention
it... Yes, it actually is...
With a std::map you can simply do
configuration[key] = value;

Yes - I am actually storing the values in a map, however (it's been a
while since I worked on that little project, so I forgot what exactly I
was trying to do) I had this work a little more sophisticated (or so I
thought ;)

Three member functions for modifying parameters:
explicit add (key, object) -> throws an exception if key exists

explicit set (key, object) -> throws an exception if key does NOT exist

tolerant add (key, list of object properties) -> creates an object
depending on the properties and adds it to the configuration, regardless
of whether it exists (then it's modified, but the category property of
the old value may be kept intact) or doesn't exist (then it's added to
the collection).

I think describing this helped to clarify my thoughts:

The mistake I made was that I called the add_or_set function from each
switch statement (using a function to pass the created object).

The better solution here would be to just create the object in the
switch statement, store it in a variable and do the modification to the
configuration collection afterwards, in one place, with the variable.

Then I can handle the modification of the collection directly and do not
need to call the explicit add (set) member functions to avoid redundant
code.

Thanks!

Lars
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top