What new capabilities do user-defined literals add to C++?
Here's a case where there is an advantage to using user-defined literals instead of a constructor call:
#include <bitset>
#include <iostream>
template<char... Bits>
struct checkbits
{
static const bool valid = false;
};
template<char High, char... Bits>
struct checkbits<High, Bits...>
{
static const bool valid = (High == '0' || High == '1')
&& checkbits<Bits...>::valid;
};
template<char High>
struct checkbits<High>
{
static const bool valid = (High == '0' || High == '1');
};
template<char... Bits>
inline constexpr std::bitset<sizeof...(Bits)>
operator"" _bits() noexcept
{
static_assert(checkbits<Bits...>::valid, "invalid digit in binary string");
return std::bitset<sizeof...(Bits)>((char []){Bits..., '\0'});
}
int
main()
{
auto bits = 0101010101010101010101010101010101010101010101010101010101010101_bits;
std::cout << bits << std::endl;
std::cout << "size = " << bits.size() << std::endl;
std::cout << "count = " << bits.count() << std::endl;
std::cout << "value = " << bits.to_ullong() << std::endl;
// This triggers the static_assert at compile time.
auto badbits = 2101010101010101010101010101010101010101010101010101010101010101_bits;
// This throws at run time.
std::bitset<64> badbits2("2101010101010101010101010101010101010101010101010101010101010101_bits");
}
The advantage is that a run-time exception is converted to a compile-time error.
You couldn't add the static assert to the bitset ctor taking a string (at least not without string template arguments).
understanding user defined string literals addition for c++20
This is confusing wording, which was copied directly from the standard:
If [the overload set] contains a literal operator template with a non-type template parameter for which
str
is a well-formed template-argument
The confusing bit is the question of what "for which str
is a well-formed template argument" specifically applies to. A direct reading of the passage from the standard suggests that "for which" refers to the "non-type template parameter", since that is the text directly preceding the words "for which". However, if you look at how the standard says the function will be invoked, you see this:
operator "" X<str>()
str
is being passed to the operator, which the implication being that an implicit conversion will take place between str
and the "non-type template parameter". That is, str
is a valid "template argument" of the overloaded function, not of the template parameter of the overloaded function. And thus, the "for which" part should refer to the "literal operator template with a non-type template parameter", not the "non-type template parameter".
That having been said, to make your code work, you need to do more than to just remove the template argument from MyType
.
You might have noticed a certain oddity in C++ surrounding non-type template parameters (NTTP). For example, NTTPs have always been able to be pointers to things. But you could never do this:
template<const char *literal> void foo() {}
foo<"literal">();
The standard expressly forbids a pointer NTTP from being initialized with a string literal. And C++20 does not change this.
Therefore, you can't take a pointer. You have to take what the literal actually is: an array. But you can't make your code work by taking const char (&in)[]
as a parameter either. A literal is not an unsized array (since an "unsized array" is not a real object type). That array parameter must be sized appropriately to the literal.
Which means that you must deduce the size from a size template parameter.
Also, other rules flat-out forbid you from ever storing a pointer to a string literal in an NTTP (directly or indirectly). So, if you want a type that represents an entire string literal in an NTTP, that NTTP type must contain an array that is sized to that size.
So the simplest, functional string literal NTTP you could build would be:
template<size_t N>
struct string_literal
{
std::array<char, N> arr_;
constexpr string_literal(const char(&in)[N]) : arr_{}
{
std::copy(in, in + N, arr_.begin());
}
};
And thanks to CTAD, you can just use template < string_literal t > auto operator ""_y()
to define your UDL.
Note that this string_literal
class explicitly includes the NUL terminator as part of the array.
User-defined literals
unsigned long long operator "" _w(unsigned long long);
unsigned operator "" _u(const char*);
int main() {
12_w; // calls operator "" _w(12ULL)
12_u; // calls operator "" _u("12")
}
A little bit changes based on the example in your link.
Here 12_w
calls operator "" _w(12ULL)
since there is a literal operator with the parameter type unsigned long long
, while 12_u
calls operator "" _u("12")
since there is only a raw literal operator.
Is there a workaround to define a user-defined literal for shorts in c++?
As explained here, the unary -
is applied to the result of 42_s
, so it seems that integral promotion cannot be avoided. Depending on applications, the following workaround might be of some use:
struct Short {
short v;
short operator+() const {
return v;
}
short operator-() const {
return -v;
}
};
Short operator"" _s(unsigned long long x) {
return Short{static_cast<short>(x)};
}
auto PositiveShort = +42_s;
auto NegativeShort = -42_s;
static_assert(std::is_same_v<decltype(PositiveShort), short>);
static_assert(std::is_same_v<decltype(NegativeShort), short>);
Overloading rules for User-defined-literals in c++0x
I believe that 13.5.8/7 clarifies this issue :
Note: literal operators and literal
operator templates are usually invoked
implicitly through user-defined
literals (2.14.8). However, except for
the constraints described above, they
are ordinary namespace-scope functions
and function templates. In particular,
they are looked up like ordinary
functions and function templates and
they follow the same overload
resolution rules.
From my understanding, regular overload resolution rules are only implied for literal operators when called outside an implicit invocation through user-defined literals.
So I think that if 2 & 3 are defined, 13_xx
calls 2 (the raw literal operator).
User defined literals definitions
template <char...> double operator "" _π(); // OK
How does this operator work? How can you call it?
1.234_π
will call operator "" _π<'1', '.', '2', '3', '4'>()
. This form allows you to detect differences in spelling that would ordinarily be undetectable (1.2
vs 1.20
, for example), and allows you to avoid rounding issues due to 1.2
not being exactly representable in even long double
.
double operator"" _Z(long double); // error: all names that begin with underscore
// followed by uppercase letter are reserved
double operator""_Z(long double); // OK: even though _Z is reserved ""_Z is allowedWhat is the difference between the above two functions?
The C++ standard defines the grammar in terms of tokens, which you can sort of interpret as words. "" _Z
is two tokens, ""
and _Z
. ""_Z
is a single token.
This distinction matters: given #define S " world!"
, and then "Hello" S
, the whitespace is what makes S
a standalone token, preventing it from being seen as a user-defined literal suffix.
For easier coding, both "" _Z
and ""_Z
syntaxes are generally allowed when defining these functions, but the "" _Z
syntax requires _Z
to be seen as an identifier. This can cause problems when an implementation predefines _Z
as a macro, or declares it as a custom keyword.
User-defined literals, underscores, and global names
What's in a name? 3 Basic concepts [basic] tells us:
4 A name is a use of an identifier (2.11), operator-function-id (13.5), literal-operator-id (13.5.8), conversion-function-id (12.3.2), or template-id (14.2) that denotes an entity or label (6.6.4, 6.1).
which we cross-reference with 13.5.8 User-defined literals [over.literal]:
literal-operator-id:
operator ""
identifier
While the name of a literal operator involves an identifier, that identifier does not denote an entity. (Or it's a different identifier and different name that denotes another entity or label altogether.) As such the name of a literal operator never starts with an underscore.
Something like operator""__w
is problematic but this is not new: int i__0;
is reserved as well.
C++0x, user-defined literals with friend operator ()
The Standard addresses this directly in the only place it mentions any restrictions on the declarations of user-defined literals, §13.5.8/2:
A declaration whose declarator-id is a literal-operator-id shall be a declaration of a namespace-scope function or function template (it could be a friend function (11.3)), an explicit instantiation or specialization of a function template, or a using-declaration (7.3.3).
If the friend is also declared at namespace scope, then there is no distinction between definition in class or namespace scope. Note that there is no requirement for definition at namespace scope, which your question as currently worded asserts.
If not declared at namespace scope, since it cannot be found by ADL, the friend could be used privately inside the class where it is scope by regular unqualified name lookup. This is the only way of declaring a literal operator which is not an external interface.
If the friend is defined inside a class template, then two instantiations of the template will generate two identically-named functions at namespace scope, which collide even though they are both invisible outside the class scope.
Related Topics
Is Multiplication and Division Using Shift Operators in C Actually Faster
Determine the Size of a C++ Array Programmatically
How Does the Ampersand(&) Sign Work in C++
Strict Aliasing Rule and 'Char *' Pointers
Best Compiler Warning Level For C/C++ Compilers
Requesting Administrator Privileges At Run Time
Overload Resolution Failure When Streaming Object Via Implicit Conversion to String
C++ Implicit Copy Constructor For a Class That Contains Other Objects
When Is a Private Constructor Not a Private Constructor
Should I Compile With /Md or /Mt
When to Pass by Reference and When to Pass by Pointer in C++
Is It a Good Practice to Place C++ Definitions in Header Files
How to Get Error Message When Ifstream Open Fails
Omitting Return Statement in C++
Winmain and Main() in C++ (Extended)
Embed Text File in a Resource in a Native Windows Application