Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it legal to explicitly specify a generic lambda's operator() template arguments?

Is the following C++ code standard compliant?

#include <iostream>

int main()
{
    [](auto v){ std::cout << v << std::endl; }.operator()<int>(42);
}

Both clang++ 3.8.0 and g++ 7.2.0 compile this code fine (the compiler flags are -std=c++14 -Wall -Wextra -Werror -pedantic-errors).

like image 688
Constructor Avatar asked Mar 20 '18 19:03

Constructor


People also ask

What are template arguments?

In C++ this can be achieved using template parameters. A template parameter is a special kind of parameter that can be used to pass a type as argument: just like regular function parameters can be used to pass values to a function, template parameters allow to pass also types to a function.

Can you template Lambda C++?

Lambdas support with C++20 template parameters, can be default-constructed and support copy-assignment, when they have no state, and can be used in unevaluated contexts. Additionally, they detect when you implicitly copy the this pointer.

Can lambdas be templated?

Lambda-expressions are not allowed in unevaluated expressions, template arguments, alias declarations, typedef declarations, and anywhere in a function (or function template) declaration except the function body and the function's default arguments.

How do you write a lambda function in C++?

Creating a Lambda Expression in C++auto greet = []() { // lambda function body }; Here, [] is called the lambda introducer which denotes the start of the lambda expression. () is called the parameter list which is similar to the () operator of a normal function.


1 Answers

This is indeed standard compliant. The standard specifies there must be a member operator(), and that it has one template argument for every occurence of auto in its paramater-declaration-clause. There is no wording that forbids providing those explicitly.

Bottom of the line: The call operator of a lambda is just a normal function (template, if generic).


For reference, the relevant standard clause:

The closure type for a non-generic lambda-expression has a public inline function call operator (16.5.4) whose parameters and return type are described by the lambda-expression’s parameter-declaration-clause and trailing-return-type respectively. For a generic lambda, the closure type has a public inline function call operator member template (17.5.2) whose template-parameter-list consists of one invented type template- parameter for each occurrence of auto in the lambda’s parameter-declaration-clause, in order of appearance. The invented type template-parameter is a parameter pack if the corresponding parameter-declaration declares a function parameter pack (11.3.5). The return type and function parameters of the function call operator template are derived from the lambda-expression’s trailing-return-type and parameter-declaration-clause by replacing each occurrence of auto in the decl-specifiers of the parameter-declaration-clause with the name of the corresponding invented template-parameter.

8.1.5.1/3 [expr.prim.lambda.closure] in N4659 (C++17), emphasize mine.

like image 81
Baum mit Augen Avatar answered Sep 29 '22 15:09

Baum mit Augen