使用自动 lambda 参数设置外部变量的类型
Setting type of an outer variable using auto lambda parameters
我正在使用大量使用回调 lambda 函数的 C++ Web 框架。正如您可能猜到的那样,lambda 的参数通常指定为 auto
,因为必须声明很长的声明。
现在我使用 decltype()
运算符来查找由 auto
推导的正确类型,以便我可以声明相同类型的向量。当 vector 声明发生在 lambda 内部时,一切都很好。
我的问题开始于此向量需要使用 lambdas auto
参数的类型信息在外部范围内声明。下面是一个简单的例子:
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.
};
这可能吗?
更新:
我使用的框架是uWebSockets
。这是示例代码:
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;
}
},
});
现在,main.cpp
中的任何地方都需要将参数传递给 lambda 函数。这就是主要问题的来源。
您可以将类型推断“前端加载”到类型别名中。
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;
};
//...
}
或者您可以使用模板。
#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;
}
这里的问题是 auto
在使用之前没有类型,auto
使它成为模板调用运算符:
#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;
}
结果是 param
可以是任意类型,在我们查看特定用法之前。
如果您知道将提供的参数,则可以应用decltype
:
#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;
}
您必须手动查看您正在初始化的类型。
通用 lambda 使用模板 operator()
创建对象。该模板的 多个 实例化并没有太多限制。
如果是这样,那么就没有 a 类型是 auto parameter
.
的类型
你在这里相对幸运,因为你用所有这些仿函数成员初始化的对象将参数放在它的定义中:
MoveOnlyFunction<void(WebSocket<SSL, true, UserData> *)> open = nullptr;
如果不想再看定义,可以写一个trait
template<typename Signature>
struct MoveOnlyFunctionTraits;
template <typename R, typename... Arguments>
struct MoveOnlyFunctionTraits<MoveOnlyFunctionTraits<R(Arguments...)> {
using result_type = R;
static constexpr auto arity = sizeof...(Arguments);
template <std::size_t I>
using argument = std::tuple_element_t<std::tuple<Arguments...>, I>;
}
template<typename Signature, std::size_t I>
using argument_t = typename MoveOnlyFunctionTraits<Signature>::template argument<I>;
这允许你拉出类型
using websocket_type = argument_t<decltype(uWS::App::WebSocketBehaviour<DataType>::open), 0>;
std::vector<websocket_type> users;
或者您可以向库提交拉取请求,公开您感兴趣的类型别名
template <bool SSL>
struct TemplatedApp {
// existing members ...
public:
template <typename DataType>
using websocket_type = WebSocket<SSL, true, DataType>;
};
然后
std::vector<uWS::App::template websocket_type<DataType> *> users;
我正在使用大量使用回调 lambda 函数的 C++ Web 框架。正如您可能猜到的那样,lambda 的参数通常指定为 auto
,因为必须声明很长的声明。
现在我使用 decltype()
运算符来查找由 auto
推导的正确类型,以便我可以声明相同类型的向量。当 vector 声明发生在 lambda 内部时,一切都很好。
我的问题开始于此向量需要使用 lambdas auto
参数的类型信息在外部范围内声明。下面是一个简单的例子:
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.
};
这可能吗?
更新:
我使用的框架是uWebSockets
。这是示例代码:
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;
}
},
});
现在,main.cpp
中的任何地方都需要将参数传递给 lambda 函数。这就是主要问题的来源。
您可以将类型推断“前端加载”到类型别名中。
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;
};
//...
}
或者您可以使用模板。
#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;
}
这里的问题是 auto
在使用之前没有类型,auto
使它成为模板调用运算符:
#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;
}
结果是 param
可以是任意类型,在我们查看特定用法之前。
如果您知道将提供的参数,则可以应用decltype
:
#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;
}
您必须手动查看您正在初始化的类型。
通用 lambda 使用模板 operator()
创建对象。该模板的 多个 实例化并没有太多限制。
如果是这样,那么就没有 a 类型是 auto parameter
.
你在这里相对幸运,因为你用所有这些仿函数成员初始化的对象将参数放在它的定义中:
MoveOnlyFunction<void(WebSocket<SSL, true, UserData> *)> open = nullptr;
如果不想再看定义,可以写一个trait
template<typename Signature>
struct MoveOnlyFunctionTraits;
template <typename R, typename... Arguments>
struct MoveOnlyFunctionTraits<MoveOnlyFunctionTraits<R(Arguments...)> {
using result_type = R;
static constexpr auto arity = sizeof...(Arguments);
template <std::size_t I>
using argument = std::tuple_element_t<std::tuple<Arguments...>, I>;
}
template<typename Signature, std::size_t I>
using argument_t = typename MoveOnlyFunctionTraits<Signature>::template argument<I>;
这允许你拉出类型
using websocket_type = argument_t<decltype(uWS::App::WebSocketBehaviour<DataType>::open), 0>;
std::vector<websocket_type> users;
或者您可以向库提交拉取请求,公开您感兴趣的类型别名
template <bool SSL>
struct TemplatedApp {
// existing members ...
public:
template <typename DataType>
using websocket_type = WebSocket<SSL, true, DataType>;
};
然后
std::vector<uWS::App::template websocket_type<DataType> *> users;