C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Explicit keyword for template parameters

From: Abdullah Qasim <iamminecraftredstoner_at_[hidden]>
Date: Sun, 1 May 2022 07:46:34 +0000
How about:

explicit template <typename T, typename U, typename ...V>
T Func(U u, V... v)

??

From: Frederick Virchanza Gotham via Std-Proposals<mailto:std-proposals_at_[hidden]>
Sent: 30 April 2022 13:07
To: std-proposals<mailto:std-proposals_at_[hidden]>
Cc: Frederick Virchanza Gotham<mailto:cauldwell.thomas_at_[hidden]>
Subject: Re: [std-proposals] Explicit keyword for template parameters

On Fri, Mar 25, 2022 at 11:09 AM organicoman wrote:
>
> Your proposal could be interesting.
> But why do you want to explicitly write the type, if you can deduce it?


One common debacle in C++ is unwanted integer promotion, especially
for beginner programmers. Let's say we have a template function whose
return type is the same as its parameter type:

    template<typename T>
    T Func(T const &arg) { /* Do something */ }

And let's say we do this:

    int main(void)
    {
        char unsigned a = 7, b = 6;

        Func( a + b );
    }

Lots of people at first glance will think here that 'Func' is being
instantiated with the type "char unsigned", when really it's being
instantiated with "int".
If the template function, 'Func', will be frequently used in such a
context, it would be better for the programmer to have to explicitly
specify the type, either:

    Func<char unsigned>(a+b);

or even:

    Func<decltype(a)>(a+b);

In my day job I write C++ for an Arduino microcontroller. I went
looking in my code just now to find the template function I wrote
earlier this month. The following function performs the mathematical
operation:

    a + b

however if this operation results in overflow then it returns:

    std::numeric_limits<T>::max();

So here's how I wrote the function:

#include <type_tratis>

template<typename T>
typename std::common_type<T>::type Add_Or_Max(T const a, T const b)
{
    static_assert( false == std::numeric_limits<T>::is_signed,
"Add_Or_Max can only be used with an unsigned integer type" );

    if ( a > (std::numeric_limits<T>::max() - b) )
    {
        return std::numeric_limits<T>::max();
    }
    else
    {
        return a + b;
    }
}

My program runs on an Arduino microcontroller, however I also compile
it as part of a simulator that runs on an x86_64 desktop PC. In the
future the simulator might run on a different kind of desktop PC, and
we might change to a 16-Bit or 64-Bit microcontroller (or even 8-Bit
-- Arduino has a C++ compiler for 8-Bit). Because of the differences
in architecture here, I am very particular about integer types, using
"std::uint16_t" and "std::int32_t" instead of short, int, long (and
also watching out for the perils of integer promotion -- e.g. uint32_t
might promote to a signed 64-Bit number). When a programmer uses my
function "Add_Or_Max", I want it to stick out like a sore thumb in the
code which integer type they're using, e.g.:

    #include <cstdint>
    using std::uint16_t;

    uint16_t my_global_var;

    int main(void)
    {
        Add_Or_Max( my_global_var, 52u ); // I don't want this to compiler

        Add_Or_Max<uint16_t>( my_global_var, 52u ); // I want this to compile
    }

And so I think it would be great if we could have explicit template
parameters as follows:

template<explicit typename T>
T Add_Or_Max(T const a, T const b)
{
    static_assert( false == std::numeric_limits<T>::is_signed,
"Add_Or_Max can only be used with an unsigned integer type" );

    if ( a > (std::numeric_limits<T>::max() - b) )
    {
        return std::numeric_limits<T>::max();
    }
    else
    {
        return a + b;
    }
}
--
Std-Proposals mailing list
Std-Proposals_at_[hidden]
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

Received on 2022-05-01 07:46:37