Home > Software engineering >  Setting type of an outer variable using auto lambda parameters
Setting type of an outer variable using auto lambda parameters

Time:09-27

I am using a C web framework that heavily uses callback lambda functions. As you may guess, parameters to lambdas are usually specified as auto due to the must to declare very long declarations.

Now I use decltype operator to find the right type deduced by auto so that I can declare a vector of the same type. When the vector declaration happens inside the lambda, everything is fine.

Where my problem starts is this vector needs to be declared in an outer scope using lambdas auto parameters' type information. Below is a simple example:

std::vector<T> vec; // I want the type information to be inferred just like vec2 from lambda below
auto func = [](auto parameter){
    std::vector<decltype(parameter)> vec2; // No problem here.
};

Is this possible?

UPDATE:

The framework I am using is uWebSockets. Here is the example code :

using DataType = std::string;

// I had to go get type information from the source code.
static std::vector<uWS::WebSocket<false, true, DataType> *> users; 

uWS::App app {};

app.ws<DataType>("/*", {
    
    .open = [](auto * ws){
        // This is also doable
        // But not accessible in other lambdas.
        static std::vector<decltype(ws)> users2;
        // users2.push_back(ws);
        users.push_back(ws);
        ws->subscribe("sensors/ /house");
    },

    .close = [](auto *ws, int code, std::string_view message){
        users.erase(std::remove(users.begin(), users.end(), ws), users.end());

        // Not possible because not accessible.
        //users2.erase(std::remove(users2.begin(), users2.end(), ws), users2.end());
        std::cout << "Client disconnected!" << std::endl;
    },

    .message = [](auto *ws, std::string_view message, uWS::OpCode opCode){
        try{
            std::string message2 = std::string(message)   std::string(" ACK");
            for(const auto & ws2 : users)
                if(ws != ws2)
                    ws2->send(message2, opCode);

        }catch(std::exception& e){
            std::cout << e.what() << std::endl;
        }
    },
});

Now, nowhere in the main.cpp, there is a need to pass a parameter to lambda functions. That's where the main problem comes from.

CodePudding user response:

Or maybe you could use templates.

#include <vector>

template<typename type_t>
void some_function(const type_t value) 
{
    std::vector<type_t> vec;
    auto func = [](const type_t& parameter) 
    {
        std::vector<type_t> vec2;
    };

    //....
}

auto get_something()
{
    // some made up complex data type returned as auto
    using some_complex_data_type_from_somewhere_t = std::vector<std::vector<int>>;
    some_complex_data_type_from_somewhere_t value{};
    return value;
}

int main()
{
    auto value = get_something();
    some_function(value);

    return 0;
}

CodePudding user response:

You can "front-load" the type inference into a type alias.

void some_function() {
  using value_type = decltype(infer_from_somewhere);
  // alt: using value_type = typename some::annoyingly<complex>::type;

  std::vector<value_type> vec;
  auto func = [](value_type parameter){
    std::vector<value_type> vec2;
  };

  //...
}

CodePudding user response:

The problem here is that auto has no type until it is used, auto make it a template call operator:

#include <iostream>

using namespace std;

int main()
{
    auto func = [](auto param){
        std::cout << param << std::endl;
    };
   func(4);     // integer call
   func("lol"); //const char* call 

    return 0;
}

The consequence is that param could have any arbitrary type, before we are looking at a specific usage.

If you know the argument which will be provided, then decltype can be applied:

#include <iostream>

using namespace std;

int main()
{
    int arg1 = 4;
    using Type1 = decltype(arg1); // type for the argument
    auto func = [](auto param){
        std::cout << param << std::endl;
    };
   func(arg1);  // Type1 call
   func("lol"); //const char* call 

    return 0;
}
  • Related