Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to make a template variable in lambda signature generic?

Suppose you have a function that takes a std::vector of any type and processes it in some way:

template<typename T>
void foo(std::vector<T> &vec) {
    // work with vec
}

Since C++14, we are able to achieve the same thing with lambdas. In this case, we call them generic lambdas, since we introduce a template-like deduction to them:

auto foo_lambda = [](std::vector<auto> &vec) {
    // work with vec
};

But our options seem quite limited to me. Suppose that I not only have to introduce a type deduction, but I also need to introduce template values. For example, let's change std::vector to std::array:

template<typename T, std::size_t size>
void foo(std::array<T, size> &arr) {
    // work with arr
}

When dealing with template functions, we are able to introduce a template value, which can be used to match argument's needs. Neat.

I wanted to achieve the same functionality with generic lambdas, but I was unable to do so.

Is there a way to introduce a similar, deduced value to a lambda expression so any std::arrays can be used with said lambda, similarily to the second version of the foo() function above?

EDIT: As stated in the comments by Evg, my vector<auto> syntax is non-standard GCC extension. For details see this answer referring to this document.

like image 308
Fureeish Avatar asked Oct 20 '18 21:10

Fureeish


People also ask

Can you template a lambda?

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.

What is the correct syntax for Lambda Expression in C++11?

Lambdas can both capture variables and accept input parameters. A parameter list (lambda declarator in the Standard syntax) is optional and in most aspects resembles the parameter list for a function. auto y = [] (int first, int second) { return first + second; };

What is capture in lambda?

A lambda expression can refer to identifiers declared outside the lambda expression. If the identifier is a local variable or a reference with automatic storage duration, it is an up-level reference and must be "captured" by the lambda expression.

How do you write lambda 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

You can use some dedicated type trait:

#include <type_traits>
#include <utility>
#include <array>

template<typename x_Whatever> struct
is_array: ::std::false_type {};

template<typename x_Item, ::std::size_t x_items_count> struct
is_array<::std::array<x_Item, x_items_count>>: ::std::true_type {};

int main()
{
    auto Do_SomethingWithArray
    {
        [](auto & should_be_array)
        {
            static_assert
            (
                is_array
                <
                    ::std::remove_reference_t<decltype(should_be_array)>
                >::value
            );            
        }
    };
    ::std::array<int, 3> a{};
    Do_SomethingWithArray(a); // Ok
    int x{};
    Do_SomethingWithArray(x); // error
}

online compiler

like image 103
user7860670 Avatar answered Sep 23 '22 03:09

user7860670