C++ Logo

std-discussion

Advanced search

Explicit and implicit parameter counts

From: Rick C. Hodgin <rick.c.hodgin_at_[hidden]>
Date: Fri, 3 Sep 2021 10:48:51 -0400
Greetings.

Since we can define explicitly required parameters, and implicitly
required parameters (populated with default values), I'd like to
propose a way to know the number of each provided to a function by its
caller.

This information would be available for use in two ways depending on
how it's referenced:

(1) As add-on named function parameters for use as use variables (for
output, storage, or passing as parameters to other functions). These
would be auto-added to the function's parameters by the compiler,
though invisible to the user unless an examination of the stack was
made:

(2) As compile-time definitions which allow for conditional
compilation, which would ultimately create versions of a function
based on provided counts and the subsequent reference-only logic.

-----[BEGIN: Example for type (1) ]-----

// Prototype
int func(int a, int b = 0, int c = 0);

// Use in code:
int main()
{
    func(0);
    func(0, 0);
    func(0, 0, 0);
    return 0;
}

// Body:
int func(int a, int b, int c)
{
    // In theory, it would use two auto-injected compiler-added parameters:
    std::cout << "Explicit count = " << __ARGS_EXPLICIT__ << std::endl;
    std::cout << "Implicit count = " << __ARGS_IMPLICIT__ <<
std::endl; << std::endl;
}

The above would be used as parameters producing output with counts of:
1 explicit, 2 implicit
2 explicit, 1 implicit
3 explicit, 0 implicit

This feature would be the equivalent of translating the actual
function definition into something like this by the compiler:
int func(int __ARGS_EXPLICIT__, int __ARGS_IMPLICIT__, int a, int b =
0, int c = 0);

With auto-injected additional parameters added by the compiler like this:
func(1, 2, 0);
func(2, 1, 0, 0);
func(3, 0, 0, 0, 0);

The compiler would auto-inject those parameters. They would be
visible on the stack, but are unnamed in the prototype or body
definition. And normal optimizations would flow from the now
re-defined internal function definition expansions.

They would only be auto-injected when those macro names were
referenced in the body function.

-----[END: Example for type (1) ]-----

.
.
.

-----[BEGIN: Example for type (2) ]-----

For the conditional compilation model, this type of logic would be used:

// Prototype
int inlist(int value, int p1, int p2 = 0, int p3 = 0);

// Use in code:
int main()
{
    int a = 1;
    int b = 2;
    int c = 3;

    if (inlist(1, a, b)) std::cout << "Yes" << std::endl;
    else std::cout << "No" << std::endl;

    if (inlist(5, a, b, c)) std::cout << "Yes" << std::endl;
    else std::cout << "No" << std::endl;

    return 0;
}

// Body:
bool inlist(int value, int p1, int p2, int p3)
{
    if (value == p1)
        return true;

    if (__ARGS_EXPLICIT__ >= __ARG_NUMBER(p2))
    {
        if (value == p2)
            return true;

        if (__ARGS_EXPLICIT__ >= __ARG_NUMBER(p3))
        {
            if (value == p3)
                return true;
        }
    }

    return false;
}

In the above example, the parameters are never actually used in
anything stored to memory; just flow-control logic. As such, they
become compile-time-only usages which can be conditionally compiled
creating two versions of the function, one for the three input
parameter case, and one for the four.

-----[END: Example for type (2) ]-----


When I asked about this feature on Stack Overflow, someone suggested
using std::optional:

stackoverflow dot com
/questions/68978101/visual-c-function-call-explicit-implicit-parameter-count

That works, but does not seem to be an appropriate solution due to
runtime overhead. In Microsoft's implementation, for example, the
std::optional form has three additional function calls on the func(0);
call lines, and the body of func() is referencing one call each for
has_value() in unoptimized mode. And in optimized mode, it is of the
type (1) form above, optimized inline rather than through calls into
func().

Use of std::optional is an unnecessary amount of overhead for the
developer, and the compiler, for something that is simple
known-at-compile-time information that could be auto-injected as
needed by the compiler.

After Stack Overflow's response, I proposed this extension as a
Microsoft-only extension on Microsoft's Visual Studio "suggest an
idea" system, and they suggested I propose it here:

developercommunity dot visualstudio dot com
/t/need-a-way-to-know-explicit-and-implicit-parameter/1517467

They suggested I offer it to the ISO C++ committee.

I offer it here for discussion.

Thank you.

--
Rick C. Hodgin

Received on 2021-09-03 09:48:54