Allowing any unsigned integral type as parameter type for literal operators
                
                    Author: MichaĆ Dominiak, griwes@griwes.info
                
                
                
                    Document number: P0345R0
                
                
                
                    Date: 2016-05-25
                
            
Introduction
                User-defined literals are a great tool for shortening code that would otherwise need to be overly verbose,
                but since the first proposal, they lacked one feature that would make writing code even simpler - supporting
                arbitrary unsigned types as arguments for operator"". Consider the following code:
            
    constexpr std::uint8_t operator "" _foo(unsigned long long value)
    {
        return value;
    }
    int main()
    {
        auto foo = 1024_foo;    // this compiles with no warnings, even though it overflows, whereas this:
        char bar = 1024;        // warns about changing the value
    }
            
            
                It should be obvious that the first should also produce a diagnostic, since it might be a result of a
                simple programming mistake. There is also another problem, which appears to be far less important, but
                still exists. Consider the following platform specific code for a platform, where std::uint64_t
                is the biggest unsigned integer type:
            
    constexpr std::uint64_t operator "" _bar(std::uint64_t value)
    {
        // ...
    }
            
            
                results in an error in both GCC and Clang, because they use unsigned long, not unsigned
                long long for std::uint64_t, at least on Linux. This is an environment-specific problem,
                but the Standard should provide a way to overcome it in a portable way.
            
Proposed solution
The proposed solution is as follows:
- 
                    Allow any unsigned type as an argument for operator "", notunsigned long longonly.
- Make narrowing in case of user defined literals ill-formed.
An additional feature gained with 1) and 2) is allowing to limit the range of values used in a user-defined literal.
                Note: this proposal doesn't propose operator "" overloading for unsigned
                integral types. Allowing such overloading would create ambiguities; it is not desirable.
            
Proposed wording changes
Change in 13.5.8 over.literal paragraph 3:
The declaration of a literal operator shall have a parameter-declaration-clause equivalent to one of the following:Add two new paragraphs before 13.5.8 over.literal paragraph 5:
const char*
unsigned char
unsigned short int
unsigned int
unsigned long int
unsigned long long int- an extended unsigned integer type ([basic.fundamental].3)
- ...
Literal operator overloading for unsigned integral types is not supported. If there exist two or more literal operator declarations with the same literal suffix identifier with a single parameter, but of different unsigned integral types, the program is ill-formed.Change in 13.5.8 over.literal paragraph 8:
If a narrowing conversion would happen when a literal operator with a single parameter of an unsigned integral type is invoked implicitly through user-defined literal, the program is ill-formed.
                    
    template <char...> int operator "" _j(const char*); // error: invalid parameter-declaration-clause
    std::uint8_t operator "" _k(std::uint8_t);
    auto l = 256_k;                                     // error: integer constant is too large for its type
    std::uint16_t operator "" _k(std::uint16_t);        // error: literal operator overloading is not supported