C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Labelled parameters

From: David Brown <david.brown_at_[hidden]>
Date: Mon, 5 Jan 2026 11:25:51 +0100
On 05/01/2026 09:10, Jan Schultke via Std-Proposals wrote:
>
>
> Strong types are never realistically going to happen. I don't want to write
>
> std::memcpy(std::memcpy_dest_ptr(to), std::memcpy_source_ptr(from),
> size);
>
> std::to_chars(begin, end, std::to_chars_base(16));
>
> I want to write
>
> std::memcpy(.dest = to, .src = from, .count = size);
> std::to_chars(begin, end, .base = 16);
>
>
> Outside of a few select places, I don't see much appetite for creating
> countless additional types. In some cases, having some kind of numeric
> range type or using std::spanwould help.
>

(This post is not a proposal - it's merely an idea that might be useful
for labelled parameters and more general use. It might also be fatally
flawed in some way that I haven't considered.)


Strong types for naming parameters have the advantage that they already
exist in the language, and already work. But they have the disadvantage
of being verbose - both in defining the types, and in their usage. You
end up with something like this (a real "Parameter" template would
likely use rvalue references) :

template <auto N, typename T> class Parameter {
     T value_;
public :
     Parameter(T v) : value_(v) {}
     explicit operator T () { return value_; }
};

namespace my_lib {
     namespace foo_param {
         using X = Parameter<[](){ return "x"; }, int>;
         using Y = Parameter<[](){ return "y"; }, int>;
     }
     int foo(foo_param::X x, foo_param::Y y) {
         int x_ { x };
         int y_ { y };
         return x_ * x_ + y_;
     }
     int foo(foo_param::Y y, foo_param::X x) {
         return foo(foo_param::X(x), foo_param::Y(y));
     }
}; // namespace ns

int bar(int x, int y) {
     return my_lib::foo(my_lib::foo_param::X(x),
                     my_lib::foo_param::Y(y));
}

int bar2(int x, int y) {
     return my_lib::foo(my_lib::foo_param::Y(y),
                     my_lib::foo_param::X(x));
}


Is there any way that this could be simplified? Suppose it were
possible to declare "foo" with :

     using namespace foo_param
     int foo(X x, Y y) {
         int x_ { x };
         int y_ { y };
         return x_ * x_ + y_;
     }
     using namespace foo_param
     int foo(Y y, X x) {
         return foo(X(x), Y(y));
     }

This new "using" would inject the "foo_param" namespace (inside the
"my_lib" namespace) into the lookup namespaces for parameters in the
function call. You still have plenty of boilerplate code for the
declaration of "foo", but it's usage now becomes :

int bar(int x, int y) {
     return my_lib::foo(X(x), Y(y));
}

which is a huge improvement.

It is also a general feature - it would not have to be restricted to
just the parameter names, but could include "using" declarations for
scoped enumerations or other identifiers that would often be convenient
for users of the function "foo". The aim is to get the benefits of
scopes and namespaces for type safety, scalability, modularity and
clarity, while reducing the visual overhead when scopes are clear from
the context.


The next step would then be a way to inject types into this "function
parameter" scope within the declaration of the function, so that the
boilerplate on the definition of "foo" could be reduced. I have no good
ideas about how that could be done neatly. But it is possible that it
could be handled using reflection - first declare an implementation
function "int foo_imp(int x, int y);" and then use a metafunction call
"auto foo = std::named_parameters(foo_imp);" to declare the function
with strong parameter types. I don't think reflection currently gives
access to the names of function parameters, however.

Received on 2026-01-05 10:25:59