Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Optional arguments or overloading?

94 views
Skip to first unread message

Mr Flibble

unread,
Feb 2, 2018, 6:09:33 PM2/2/18
to
Hi!

I contend that one should prefer function overloading to optional
arguments because:

1) one should prefer a function with fewer arguments to a function with
more arguments;
2) optional arguments are unsafe when used with virtual functions as
there is no language requirement that the default argument is the same
value in the base as in the derived;
3) an overloaded function can simply call another overload with an extra
parameter simulating the default argument;
4) overloading is only credible if a rule is enforced (through some
coding standard) such that functions with the same name in the same
namespace are related semantically but it is common sense to do this anyway.

I am not proposing that default arguments should never be used just that
if there is a choice where either can be used then one should prefer
overloading.

My position is at odds with Mr Stroustrup's C++ Core Guidelines which
states:

"There is no guarantee that a set of overloaded functions all implement
the same semantics. The use of default arguments can avoid code
replication."

However I believe the first part is addressed by (4) above and the
second part is addressed by (3) above.

Am I mistaken?

Thoughts?

/Flibble

--
"Suppose it’s all true, and you walk up to the pearly gates, and are
confronted by God," Bryne asked on his show The Meaning of Life. "What
will Stephen Fry say to him, her, or it?"
"I’d say, bone cancer in children? What’s that about?" Fry replied.
"How dare you? How dare you create a world to which there is such misery
that is not our fault. It’s not right, it’s utterly, utterly evil."
"Why should I respect a capricious, mean-minded, stupid God who creates
a world that is so full of injustice and pain. That’s what I would say."

Marcel Mueller

unread,
Feb 2, 2018, 6:15:29 PM2/2/18
to
On 03.02.18 00.09, Mr Flibble wrote:
> I am not proposing that default arguments should never be used just that
> if there is a choice where either can be used then one should prefer
> overloading.

If you have /many/ optional arguments, overloading is no longer an
option as it would require 2 to the power of N overloads.


Marcel

Mr Flibble

unread,
Feb 2, 2018, 6:22:02 PM2/2/18
to
Having /many/ optional arguments is usually a pathological design
mistake; I did say that one should prefer a function with fewer
arguments to a function with more arguments.

Richard

unread,
Feb 2, 2018, 6:38:32 PM2/2/18
to
[Please do not mail me a copy of your followup]

Marcel Mueller <news.5...@spamgourmet.org> spake the secret code
<p52re8$m5e$1...@gwaiyur.mb-net.net> thusly:
Many arguments to a function usually indicates that there is some
other small-to-medium level abstraction awaiting extraction from your
existing code.

The canonical example is a 2D point class instead of constantly
passing x and y separately everywhere.

For large bags of arguments where most of the time you have reasonable
defaults, the "builder pattern" combined with method chaining is a
readable alternative. Here's a blog post I wrote about using builder
pattern to initialize such bags of argument structs used in the
Direct3D API:
<https://legalizeadulthood.wordpress.com/2009/07/12/description-helpers-for-direct3d-10-10-1-and-11/>

I've used similar builder patterns to create Qt widgets and layouts.
Doing this made the code smaller and eliminated a bunch of temporary
variable names whose only purpose was to capture a value so that more
properties could be set on it before the value was used. With
appropriate indentation used to reveal layout/widget hierarchy, you
can concisely describe a bunch of nested widgets and layouts in a way
that their visual appearance in code reflects their relationship in
the parent/child hierarchy as well.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Terminals Wiki <http://terminals-wiki.org>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>

Alf P. Steinbach

unread,
Feb 3, 2018, 1:43:56 AM2/3/18
to
No, I think you're conflating things here.

Defaulted arguments in a call are always at the end of the argument
list, so it's simply N overloads.

If all arguments have defaults then that means writing O(N^2) formal
argument declarations, but that's something else.

---

The situation with 2^N overloads comes about when one desires to emulate
perfect forwarding of N arguments in C++03, with const or non-const for
each argument. Since there are 2^N combinations of argument types that's
also the number of overloads.

---

That said, I think core language support for named arguments would be
nice, especially for GUI stuff. The Boost Parameters sub-library goes
some way towards solving it but only via a brittle and extreme-ugly
macro magic front-end, and a hard-to-grok too clever implementation
(essentially they identify arguments via types, types as names of
arguments). Also, as I recall it doesn't support constructors.


Cheers!,

- Alf

Marcel Mueller

unread,
Feb 3, 2018, 2:48:09 AM2/3/18
to
On 03.02.18 00.38, Richard wrote:
> [Please do not mail me a copy of your followup]
>
> Marcel Mueller <news.5...@spamgourmet.org> spake the secret code
> <p52re8$m5e$1...@gwaiyur.mb-net.net> thusly:
>> If you have /many/ optional arguments, overloading is no longer an
>> option as it would require 2 to the power of N overloads.
>
> Many arguments to a function usually indicates that there is some
> other small-to-medium level abstraction awaiting extraction from your
> existing code.

A typical use case is the initialization of UI metadata. Let's have
business objects with a bunch of properties. If you do not want to
pollute this objects with visualization hints you need a dictionary with
this information in the GUI layer where either the data type or, more
refined, the BO class and the field is the key and the visualization
styles and methods are the values.
I have to admit that this pattern is not that useful in the C++ language
because of the lack of named parameters at function calls.

> For large bags of arguments where most of the time you have reasonable
> defaults, the "builder pattern" combined with method chaining is a
> readable alternative.

This is definitely an option. But I would call it "work around" for the
missing named parameters to some degree. Furthermore, It is quite hard
to keep it all constexpr as it always requires the temporary object that
carries all the parameters.


Marcel

Ian Collins

unread,
Feb 3, 2018, 3:47:25 AM2/3/18
to
On 02/03/2018 08:47 PM, Marcel Mueller wrote:
> On 03.02.18 00.38, Richard wrote:
>> [Please do not mail me a copy of your followup]
>>
>> Marcel Mueller <news.5...@spamgourmet.org> spake the secret code
>> <p52re8$m5e$1...@gwaiyur.mb-net.net> thusly:
>>> If you have /many/ optional arguments, overloading is no longer an
>>> option as it would require 2 to the power of N overloads.
>>
>> Many arguments to a function usually indicates that there is some
>> other small-to-medium level abstraction awaiting extraction from your
>> existing code.
>
> A typical use case is the initialization of UI metadata. Let's have
> business objects with a bunch of properties. If you do not want to
> pollute this objects with visualization hints you need a dictionary with
> this information in the GUI layer where either the data type or, more
> refined, the BO class and the field is the key and the visualization
> styles and methods are the values.
> I have to admit that this pattern is not that useful in the C++ language
> because of the lack of named parameters at function calls.

In similar situations I have used functions that take just one
parameter: a JSON blob. The optional bits were indicated by the
presence or otherwise of fields in the blob. For example when creating
a file there are a mix mandatory fields (name) and optional fields (such
as meta data not inherited form parent).

--
Ian.

David Brown

unread,
Feb 4, 2018, 6:38:38 AM2/4/18
to
On 03/02/18 07:43, Alf P. Steinbach wrote:

>
> That said, I think core language support for named arguments would be
> nice, especially for GUI stuff. The Boost Parameters sub-library goes
> some way towards solving it but only via a brittle and extreme-ugly
> macro magic front-end, and a hard-to-grok too clever implementation
> (essentially they identify arguments via types, types as names of
> arguments). Also, as I recall it doesn't support constructors.
>

Named arguments would be a huge benefit to C++, IMHO. They would
clearly be useful in cases where you have lots of parameters, perhaps
with many default parameters. But they would also be useful when you
have only a few parameters. If you have a function "drawBox" taking 4
int parameters, and see "drawBox(100, 200, 500, 700)" - is that "x, y,
width, height", or "x1, y1, x2, y2", or something else? It is
especially unclear when some numpty thinks it is a good idea to declare
the function as "void drawBox(int, int, int, int)" instead of naming the
parameters.


Marcel Mueller

unread,
Feb 4, 2018, 7:33:12 AM2/4/18
to
On 04.02.18 12.38, David Brown wrote:
> Named arguments would be a huge benefit to C++, IMHO.

Ack.

But there are side effects because the name of the arguments become part
of the public API.
First of all programmers might not be aware of that and rename their
args due to of refactoring. OK, one could refactor only the names in the
/implementation/.
Furthermore consistency aspects may arise when overriding functions with
different argument names. Restrictions would be helpful but they would
break existing code.

> They would
> clearly be useful in cases where you have lots of parameters, perhaps
> with many default parameters. But they would also be useful when you
> have only a few parameters.

I would also add overload resolution: named parameters could
disambiguate calls.
It might even be allowed to have two overloads with identical types but
distinct semantics, e.g. substring(int start, int length) vs.
substring(int start, int end). Unfortunately the latter requires ABI
changes.


Marcel

Marcel Mueller

unread,
Feb 4, 2018, 7:44:21 AM2/4/18
to
On 03.02.18 07.43, Alf P. Steinbach wrote:
>> If you have /many/ optional arguments, overloading is no longer an
>> option as it would require 2 to the power of N overloads.
>
> No, I think you're conflating things here.
>
> Defaulted arguments in a call are always at the end of the argument
> list, so it's simply N overloads.

Comparing to the current language standard you are right. A C++ function
with N optional arguments can only replace N+1 overloads.

> If all arguments have defaults then that means writing O(N^2) formal
> argument declarations, but that's something else.

No, it is still 2^N as each argument can either exist or not. O(N^2) is
typical for pair correlations.
Or are you talking about a combination of overloads an default arguments?


Marcel

Robert Wessel

unread,
Feb 4, 2018, 11:02:23 AM2/4/18
to
Unless I've missed the change, it's N. If you have three default
arguments, you can call the function with zero, one, two or three
arguments, but then you'll get all three, the first two, the first or
none of the default arguments. You can't call and get only the first
and third defaults, while passing the second argument.

David Brown

unread,
Feb 4, 2018, 12:01:15 PM2/4/18
to
On 04/02/18 13:33, Marcel Mueller wrote:
> On 04.02.18 12.38, David Brown wrote:
>> Named arguments would be a huge benefit to C++, IMHO.
>
> Ack.
>
> But there are side effects because the name of the arguments become part
> of the public API.

I see that as a bonus, and a good thing. Pick good names for your
arguments that say what they do - and use them for the declarations
/and/ definitions. I would be absolutely fine with the idea that these
are required to match, that mismatches would be a compilation (or
linking) error, and even that they are part of name mangling.

> First of all programmers might not be aware of that and rename their
> args due to of refactoring. OK, one could refactor only the names in the
> /implementation/.
> Furthermore consistency aspects may arise when overriding functions with
> different argument names. Restrictions would be helpful but they would
> break existing code.
>

Extra limitations on argument names would indeed be a compatibility
problem. The solution would simply be to say that only functions where
the identifiers matched up could be used for named argument calls.


>> They would
>> clearly be useful in cases where you have lots of parameters, perhaps
>> with many default parameters.  But they would also be useful when you
>> have only a few parameters.
>
> I would also add overload resolution: named parameters could
> disambiguate calls.
> It might even be allowed to have two overloads with identical types but
> distinct semantics, e.g. substring(int start, int length) vs.
> substring(int start, int end). Unfortunately the latter requires ABI
> changes.
>

It does not need any ABI calls when you have named arguments. The
compiler has the original declaration, which gives the order required
for the definition (which must match). If you write "substring(.start =
2, .length = 10);" and then "substring(.length = 10, .start = 2);", then
the compiler will match up the parameter order to fit the declaration
(and therefore the definition).

This is the way it works in many other programming languages - named
arguments is standard practice in modern language design, and C++ stands
out by missing this feature.

Marcel Mueller

unread,
Feb 4, 2018, 1:47:14 PM2/4/18
to
On 04.02.18 18.01, David Brown wrote:
>> I would also add overload resolution: named parameters could
>> disambiguate calls.
>> It might even be allowed to have two overloads with identical types
>> but distinct semantics, e.g. substring(int start, int length) vs.
>> substring(int start, int end). Unfortunately the latter requires ABI
>> changes.
>
> It does not need any ABI calls when you have named arguments. The
> compiler has the original declaration, which gives the order required
> for the definition (which must match).

You cannot define two functions with the same signature that differ only
in the parameter names. Their mangled symbol names would be the same.


Marcel

Öö Tiib

unread,
Feb 4, 2018, 2:04:21 PM2/4/18
to
Name mangling isn't regulated by any standard. What is or isn't
part of function's signature is. But standards will change with
time.

Richard Damon

unread,
Feb 4, 2018, 2:28:55 PM2/4/18
to
Name mangling is normally specified as part of the C++ ABI, as that is
required to get cross tool compatibility.

David Brown

unread,
Feb 4, 2018, 2:54:04 PM2/4/18
to
I know - and I would not want to. Named arguments would mean there
would be even fewer cases where you might be tempted to have the same
signature and different semantics - especially if you allowed a way to
say that the function /required/ named arguments (so that you could not
write "substring(1, 4)" but would be required to write either
"substring(.start = 1, .length = 4)" or "substring(.start = 1, .end =
4)". You would need to have such requirements added into the name
mangling - but that would be fine to implement, and not unprecedented
(it's like adding noexcept to the function's type in C++17).


Öö Tiib

unread,
Feb 4, 2018, 3:09:12 PM2/4/18
to
I did not try to say that name mangling does not exist at all but that
it is implementation-specific. In general, C++ ABI is so
implementation-specific that two pieces of compiled C++ can be linked
together only
* when those were compiled with exactly same version of C++ compiler
with same compiling options
* or when every symbol exchanged between those is extern "C".

Yes, some platform vendors who want to make their own programming
languages compatible with C++ (like Apple or Oracle) do fair attempts
to define C++ ABI platform-widely but that is more exception than
actual reality and also the results of their attempts are not
reliable in practice.

Chris Vine

unread,
Feb 4, 2018, 3:36:14 PM2/4/18
to
On Sun, 4 Feb 2018 12:09:03 -0800 (PST)
Öö Tiib <oot...@hot.ee> wrote:
[snip]
> I did not try to say that name mangling does not exist at all but that
> it is implementation-specific. In general, C++ ABI is so
> implementation-specific that two pieces of compiled C++ can be linked
> together only
> * when those were compiled with exactly same version of C++ compiler
> with same compiling options
> * or when every symbol exchanged between those is extern "C".
>
> Yes, some platform vendors who want to make their own programming
> languages compatible with C++ (like Apple or Oracle) do fair attempts
> to define C++ ABI platform-widely but that is more exception than
> actual reality and also the results of their attempts are not
> reliable in practice.

The ABI is implementation specific, although clang has adopted the same
conventions as gcc. But I do not think the rest is as bleak as you
suggest.

What you say about that may be true of Visual C++ but not of gcc and
clang. They try hard not to break ABI, and the last ABI break, which
was in the standard library and not concerned with the
compiler/mangling conventions themselves, was forced on them by changes
required by C++11. And even then there is a compiler option to use the
old (non-C++11 conforming) ABI (as I recall this is concerned with
string copy on write and O(1) complexity of std::list::size()).

Leaving aside the C++11/C++98 option I have mentioned, with gcc and
clang in practice you can reliably link with system provided C++
libraries irrespective of the flags you apply to your project, provided
you do not go out of your way to create incompatibility.

Chris

Robert Wessel

unread,
Feb 4, 2018, 3:57:54 PM2/4/18
to
On Sun, 4 Feb 2018 14:28:41 -0500, Richard Damon
<Ric...@Damon-Family.org> wrote:
So the ABI would need an update. Adding a new primitive type to C++
would require the same. FWIW, most of the name mangling scheme appear
to have plenty of currently undefined sequences which would be used
for some define data needing encoding. Such a thing might well be
backwards compatible as well. Yes, your older compiler won't be able
to call the function with the new signature features, but the old
versions will still be fine.

Richard Damon

unread,
Feb 4, 2018, 4:39:09 PM2/4/18
to
On 2/4/18 3:57 PM, Robert Wessel wrote:
> On Sun, 4 Feb 2018 14:28:41 -0500, Richard Damon
> <Ric...@Damon-Family.org> wrote:
>
A non-backwards compatible update. An important distinction.

If a new type is added, then a mangling code could be added, and all
previous libraries that of course didn't use that type, would still be
usable.

For the standard to now allow overloading based on parameter names, then
the mangling for existing (compiled) code would need to change, so
existing compiled version are effectively unusable. This is a very high
cost hurdle to consider for such a language change.

Öö Tiib

unread,
Feb 4, 2018, 4:51:41 PM2/4/18
to
On Sunday, 4 February 2018 22:36:14 UTC+2, Chris Vine wrote:
> On Sun, 4 Feb 2018 12:09:03 -0800 (PST)
> Öö Tiib <oot...@hot.ee> wrote:
> [snip]
> > I did not try to say that name mangling does not exist at all but that
> > it is implementation-specific. In general, C++ ABI is so
> > implementation-specific that two pieces of compiled C++ can be linked
> > together only
> > * when those were compiled with exactly same version of C++ compiler
> > with same compiling options
> > * or when every symbol exchanged between those is extern "C".
> >
> > Yes, some platform vendors who want to make their own programming
> > languages compatible with C++ (like Apple or Oracle) do fair attempts
> > to define C++ ABI platform-widely but that is more exception than
> > actual reality and also the results of their attempts are not
> > reliable in practice.
>
> The ABI is implementation specific, although clang has adopted the same
> conventions as gcc. But I do not think the rest is as bleak as you
> suggest.

Experiences differ.

> Leaving aside the C++11/C++98 option I have mentioned, with gcc and
> clang in practice you can reliably link with system provided C++
> libraries irrespective of the flags you apply to your project, provided
> you do not go out of your way to create incompatibility.

I did not mind some awful ideas like trying to mix different boost
versions or something. I also focus in practice. It seems that linking
with GCC 4.9 (2014+) some binaries compiled with GCC 5 (2015+) do fail.

I do not doubt there are great guys working on GCC who do good job but
the C++ is not easy beast to tame. So typical approach is not to use
too fresh compilers for real production but let these mature a bit (for
example for two years). So usage of GCC 4.9.4(2016) with GCC 5.5(2017)
in mix feels more plausible than usage of 6 or 7 series (so I don't
know how ABI compatible those are).

Robert Wessel

unread,
Feb 4, 2018, 5:07:49 PM2/4/18
to
On Sun, 4 Feb 2018 16:38:55 -0500, Richard Damon
<Ric...@Damon-Family.org> wrote:

>On 2/4/18 3:57 PM, Robert Wessel wrote:
>> On Sun, 4 Feb 2018 14:28:41 -0500, Richard Damon
>> <Ric...@Damon-Family.org> wrote:
>>
I don't follow. Unless a function had a signature that included named
parameters, its mangled name would not change. Any previously
compiled code would, by definition, be unchanged.

Chris Vine

unread,
Feb 4, 2018, 5:15:40 PM2/4/18
to
On Sun, 4 Feb 2018 13:51:29 -0800 (PST)
gcc-4.9 and gcc-5.1 are by default incompatible in the standard library
with respect to std::string and std::list, as I mentioned. gcc-5 broke
ABI in its standard library to conform with C++11. You can however use
the old ABI in your project with the _GLIBCXX_USE_CXX11_ABI=0
environmental variable. If you set that correctly, gcc-4 and gcc-5
code is compatible.

As I mentioned, I do not think you will find any other
incompatibilities between gcc-3.2 onwards and the current gcc-7.3.

If you are interested in the ABI break, there is more here:
https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html

Chris


Chris Vine

unread,
Feb 4, 2018, 5:22:11 PM2/4/18
to
On Sun, 4 Feb 2018 22:15:25 +0000
Chris Vine <chris@cvine--nospam--.freeserve.co.uk> wrote:
> gcc-4.9 and gcc-5.1 are by default incompatible in the standard
> library with respect to std::string and std::list, as I mentioned.
> gcc-5 broke ABI in its standard library to conform with C++11. You
> can however use the old ABI in your project with the
> _GLIBCXX_USE_CXX11_ABI=0 environmental variable. If you set that
> correctly, gcc-4 and gcc-5 code is compatible.
>
> As I mentioned, I do not think you will find any other
> incompatibilities between gcc-3.2 onwards and the current gcc-7.3.
>
> If you are interested in the ABI break, there is more here:
> https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html

Perhaps I should add that my working version of gcc in my build system
is compiled with the --with-default-libstdcxx-abi=c++98 option, so to
use the new ABI a project needs explicitly to opt in with the
_GLIBCXX_USE_CXX11_ABI=1 environmental variable[1]. This means any
binaries it provides are by default compatible with everything from
gcc-3.2 onwards.

Chris

[1] By default, gcc provides both ABIs and will pick the right one for
any particular project depending on how the _GLIBCXX_USE_CXX11_ABI
environmental variable is set.

Richard Damon

unread,
Feb 4, 2018, 5:49:55 PM2/4/18
to
Currently, the presence or absence of parameter names in the prototype
doesn't matter, and in most cases in my experience they are there (they
help greatly with documenting the code in the header). This means that
new code compiled with new mangling rules would see that prototype as
specifying named parameters and thus mangle the call, but the previous
compiled library wouldn't have used that mangling (since might not have
existed at the time).

If some new syntax was invented to require some change in the prototype
so it wouldn't have been legal previously, then it could be added, but
that wouldn't be the examples shown.

Alf P. Steinbach

unread,
Feb 4, 2018, 6:13:09 PM2/4/18
to
I'm talking about the total number of formal argument specifications in
all overloads.

E.g.

foo()
foo( int )
foo( int, int )
foo( int, int, int )

to emulate

foo( int = 1, int = 2, int = 3 )

So the overloads have 0+1+2+3 = (4*3)/2 = 6 formal argument
specifications, and more generally (N+1)*N/2 = 0.5*(N^2 + N). Or in
short O(N^2). Sorry for skipping the math in the earlier posting!

Cheers!,

- Alf

Öö Tiib

unread,
Feb 5, 2018, 2:16:14 AM2/5/18
to
I'm not sure if signatures of functions have to be altered at all for
making named parameters. For example that proposal
http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2014/n4172.htm
seems to make it responsibility of compiler, rather than linker.

Cholo Lennon

unread,
Feb 5, 2018, 10:57:28 AM2/5/18
to
On 02/02/18 20:09, Mr Flibble wrote:
> Hi!
>
> I contend that one should prefer function overloading to optional
> arguments because:
>
> 1) one should prefer a function with fewer arguments to a function with
> more arguments;
> 2) optional arguments are unsafe when used with virtual functions as
> there is no language requirement that the default argument is the same
> value in the base as in the derived;
> 3) an overloaded function can simply call another overload with an extra
> parameter simulating the default argument;
> 4) overloading is only credible if a rule is enforced (through some
> coding standard) such that functions with the same name in the same
> namespace are related semantically but it is common sense to do this
> anyway.
>
> I am not proposing that default arguments should never be used just that
> if there is a choice where either can be used then one should prefer
> overloading.
>
> My position is at odds with Mr Stroustrup's C++ Core Guidelines which
> states:
>
> "There is no guarantee that a set of overloaded functions all implement
> the same semantics. The use of default arguments can avoid code
> replication."
>
> However I believe the first part is addressed by (4) above and the
> second part is addressed by (3) above.
>
> Am I mistaken?
>
> Thoughts?
>

Well, my experience with Java (which lacks of optional arguments)
sometimes is frustating: I have multiple function definitions when just
one would be enough (and now with Java 8's Optional<T> the situation is
worse). Having said that, I agree with Stroustroup that the use of
default arguments can avoid code replication.

Also I admit that I don't like many optional arguments in a function. I
would prefer to have something like Python's named parameters.

Regards

--
Cholo Lennon
Bs.As.
ARG

Christian Gollwitzer

unread,
Feb 5, 2018, 11:53:54 AM2/5/18
to
Am 03.02.18 um 09:47 schrieb Ian Collins:
This is more or less the approach which scripting languages like Python
are taking, which gives a reasonable syntax but overhead, because the
JSON must be parsed at runtime.

With C++17, I can imagine there is a solution which avoids the runtime
parsing. Initializer lists, variadic templates, ... ,

Would it be possible to do something like this:

function(arg1, arg2, {{"option1", arg}, {"option2", arg}})

? Bonus points if the "option" strings are evaluated at compile time.

Christian


Ian Collins

unread,
Feb 5, 2018, 5:23:16 PM2/5/18
to
On 02/06/2018 05:53 AM, Christian Gollwitzer wrote:
> Am 03.02.18 um 09:47 schrieb Ian Collins:
>> On 02/03/2018 08:47 PM, Marcel Mueller wrote:
>>> A typical use case is the initialization of UI metadata. Let's have
>>> business objects with a bunch of properties. If you do not want to
>>> pollute this objects with visualization hints you need a dictionary with
>>> this information in the GUI layer where either the data type or, more
>>> refined, the BO class and the field is the key and the visualization
>>> styles and methods are the values.
>>> I have to admit that this pattern is not that useful in the C++ language
>>> because of the lack of named parameters at function calls.
>>
>> In similar situations I have used functions that take just one
>> parameter: a JSON blob.  The optional bits were indicated by the
>> presence or otherwise of fields in the blob.  For example when creating
>> a file there are a mix mandatory fields (name) and optional fields (such
>> as meta data not inherited form parent).
>
> This is more or less the approach which scripting languages like Python
> are taking, which gives a reasonable syntax but overhead, because the
> JSON must be parsed at runtime.

In my case, the applications were related filesystem replication, so
data had to be parsed at run time. JSON was a natural on the wire format.

> With C++17, I can imagine there is a solution which avoids the runtime
> parsing. Initializer lists, variadic templates, ... ,
>
> Would it be possible to do something like this:
>
> function(arg1, arg2, {{"option1", arg}, {"option2", arg}})
>
> ? Bonus points if the "option" strings are evaluated at compile time.

The main benefit with the blob approach was all of the (what would be)
optional information was in the blob, allowing all of the functions in
the receiver to have the same interface. So the top level dispatcher
(based a command field) was easy to write either as table driven or an
if/else tree.

Having the optional information also kept the decision logic local to
the function that processed a particular element. Something like:

void newFile( JSON::Object blob )
{
createFile( blob );

applyACL( blob );
}

void createFile( JSON::Object blob )
{
if( !blob.has( "name" )
throw std::runtime_error("File must have a name!");

...
}

void applyACL( JSON::Object blob )
{
if( !blob.has( "ACL" )
return;

...
}

--
Ian.

Robert Wessel

unread,
Feb 5, 2018, 9:05:01 PM2/5/18
to
On Sun, 4 Feb 2018 17:49:42 -0500, Richard Damon
I was assuming that a function that allowed named parameters would
require those to be defined explicitly. Not unlike the way optional
parameters are specified. But yes, if you just started allowing it on
any function parameters where names are included in the definition, it
would probably be more difficult to do in a backwards compatible
manner, if possible at all.
0 new messages