使用函数成员的值创建 std::function which returns 变体。分段故障
Create std::function which returns variant with a value of a function member. Segmentation fault
我正在编写一个包装器 class 以将自定义结构成员变量包装到变体中。
给定对结构对象的引用,std::function 必须 return 一个变体,它包含特定成员的值 - std::function 最初是用它创建的。这意味着,我需要在创建函数时保存指向指定 class 成员的指针。
此代码可以编译,但是当我尝试调用函数对象时,出现分段错误。为什么会发生以及如何解决?
#include <functional>
#include <variant>
#include <iostream>
struct Foo
{
int a,
b;
char c;
double d,
e;
};
template <typename Struct, typename ... VarTypes>
struct WrapMemberGet
{
template <typename T>
static std::function<std::variant<VarTypes...>(const Struct&)>
WrapGet(T(Struct::*mem_ptr))
{
return [&](const Struct& s)
{
return std::variant<VarTypes...>(s.*mem_ptr);
};
}
};
int main(int argc, const char **argv)
{
Foo f{4, 8, 15, 16, 23};
auto get_a = WrapMemberGet<Foo, char, int ,double>::WrapGet(&Foo::a);
std::variant<char, int, double> var = get_a(f); // this must hold int = 4
return 0;
}
复制捕获以避免悬空引用:
template <typename T>
static std::function<std::variant<VarTypes...>(const Struct&)>
WrapGet(T(Struct::*mem_ptr))
{
return [=](const Struct& s)
// ^
{
return std::variant<VarTypes...>(s.*mem_ptr);
};
}
您的 WrapGet
函数通过值获取一个指向成员函数的指针,并且在您的函数内部,您正在捕获该指针作为 lambda 内部的引用。这意味着在函数结束后,使用 lambda 内部的引用是悬空的,使用它会调用 UB。
为了避免它按值捕获它,而不是在 lambda 中创建本地副本。
return [=](const Struct& s)
{
return std::variant<VarTypes...>(s.*mem_ptr);
};
我正在编写一个包装器 class 以将自定义结构成员变量包装到变体中。 给定对结构对象的引用,std::function 必须 return 一个变体,它包含特定成员的值 - std::function 最初是用它创建的。这意味着,我需要在创建函数时保存指向指定 class 成员的指针。
此代码可以编译,但是当我尝试调用函数对象时,出现分段错误。为什么会发生以及如何解决?
#include <functional>
#include <variant>
#include <iostream>
struct Foo
{
int a,
b;
char c;
double d,
e;
};
template <typename Struct, typename ... VarTypes>
struct WrapMemberGet
{
template <typename T>
static std::function<std::variant<VarTypes...>(const Struct&)>
WrapGet(T(Struct::*mem_ptr))
{
return [&](const Struct& s)
{
return std::variant<VarTypes...>(s.*mem_ptr);
};
}
};
int main(int argc, const char **argv)
{
Foo f{4, 8, 15, 16, 23};
auto get_a = WrapMemberGet<Foo, char, int ,double>::WrapGet(&Foo::a);
std::variant<char, int, double> var = get_a(f); // this must hold int = 4
return 0;
}
复制捕获以避免悬空引用:
template <typename T>
static std::function<std::variant<VarTypes...>(const Struct&)>
WrapGet(T(Struct::*mem_ptr))
{
return [=](const Struct& s)
// ^
{
return std::variant<VarTypes...>(s.*mem_ptr);
};
}
您的 WrapGet
函数通过值获取一个指向成员函数的指针,并且在您的函数内部,您正在捕获该指针作为 lambda 内部的引用。这意味着在函数结束后,使用 lambda 内部的引用是悬空的,使用它会调用 UB。
为了避免它按值捕获它,而不是在 lambda 中创建本地副本。
return [=](const Struct& s)
{
return std::variant<VarTypes...>(s.*mem_ptr);
};