The following is valid C++ code which may look a little confusing to those unfamiliar with the language or with the concepts:
1auto funny = [x = 42]<typename> requires (not not []{}) [[nodiscard("bad")]] [[maybe_unused]] [[,,,]] (auto&&...) constexpr mutable noexcept(true) [[]] [[for::if({([[]])}[{}])]] -> int requires true { return x; }.template operator()<void>();
But what does it mean? First let us format it a little nicer:
1auto funny = [x = 42]<typename>
2 requires (not not []{})
3 [[nodiscard("bad")]]
4 [[maybe_unused]]
5 [[,,,]]
6 (auto&&...)
7 constexpr mutable noexcept(true)
8 [[]]
9 [[for::if({([[]])}[{}])]]
10 -> int
11 requires true
12{
13 return x;
14}.template operator()<void>();
Let's break it down: In essence, this code defines and immediately invokes a highly decorated lambda function that always returns 42. The numerous attributes and specifiers don't affect its functionality too much but demonstrate various C++ features.
auto funny =: This declares a variable named funny whose type will be deduced from the right-hand side. What is this type? An int.
Lambdas are a way to define an anonymous function, it's like a quick disposable function that we want to treat more like a variable than an actual function that exists as a symbol in the compiled code.
For more info, see cppreference - Lambda expression.
[x = 42]: This is a lambda capture that creates a variable x initialized to 42 within the lambda's scope. Captures are meant as a way to introduce outside variables to lambdas and are put in the square brackets. so in this case this is pointless since x is constant.
<typename>: This makes the lambda a template (any function, including lambdas can be made a template, to use a generic type), though no template parameter is used. The keyword typenamecan be used interchangeably with class when declaring template parameters. In this case however, the template parameter isn't named (i.e. <typename T>) . Why is this feature in the language? sometimes you may not need the template argument, and so making it anonymous makes it clear to programmer that the argument is not used anywhere in the class, although it's not that necessary. It is similar to the way a function with an unnamed parameter is allowed:
1void f(int) //allowed
2{
3}
requires (not not []{}): This is a requires clause that always evaluates to true. The double negation of an empty lambda is always true.
it is used in template definitions to constrain the type parameter of the template. (Note In this case the template has no type parameter). For example see the following code block.
For more info, see cppreference - Requires expression.
1template<typename T>
2concept Addable = requires (T a, T b)
3{
4 a + b; // "the expression “a + b” is a valid expression that will compile"
5};
[[nodiscard("bad")]]: This, and all blocks surrounded by double square brackets are attributes. this once specifically is specifying that the return value shouldn't be discarded. If it is, the compiler should warn with the message "bad".
Attributes provide the unified standard syntax for implementation-defined language extensions. For example, a certain implementation of the language can implement a [[maybe_unused]] attribute that can be applied to a variable, that allows that type to surpress warnings by the compiler if that variable is unused.
For more info, see cppreference - Attribute specifier sequence.
[[maybe_unused]]: This attribute suggests that the function may not be used, suppressing potential warnings.
[[,,,]]: This is not standard C++. It appears to be a custom or ill-formed attribute. (Which is legal and does nothing).
(auto&&...): This is another part of the lambda syntax, specifically the argument block. It declares the lambda to accept any number of forwarding references as arguments.
constexpr mutable noexcept(true): These are specifiers that towards the lambda that make it:
- Potentially usable in constant expressions
- Able to modify its captured variables
- Guaranteed not to throw exceptions
[[]]: An empty attribute. Yes they can come after the standard specifiers and after the argument block.
[[for::if({([[]])}[{}])]]: Another non-standard attribute. It's syntactically valid as an attribute but doesn't have any standard meaning. I don't think for::if({([[]])}[{}]). for::if is not even a thing.
-> int: Specifies that the lambda returns an int.
requires true: Another requires clause that's always true.
{ return x; }: The body of the lambda, which simply returns the captured x (42).
.template operator()<void>(): This immediately invokes the lambda by calling its operator() method. (Every lambda has an operator() that allows it to be called like a function). Treating it as a function template (template which is allowed to prevent parsing ambiguity) and explicitly specifying void as the template argument (and no invocation arguments (remember auto&&...?) are passed.