c++ - 成员变量指针的函数参数包
问题描述
我正在尝试通过嵌套成员指针访问结构中的变量:
#include <iostream>
typedef struct {
int a;
int b;
} bar;
typedef struct {
int c;
bar d;
} baz;
template <typename obj, class C1, class C2, typename T1, typename T2>
T2 test1(const obj& obj_, T1 C1::* field1_, T2 C2::* field2_)
{
return (obj_.*field1_).*field2_;
}
int main()
{
baz myObj;
test1(myObj, &baz::d, &bar::b);
}
如何将函数测试转换为可变参数函数,以便我可以将变量“深度”的变量访问到结构中?我尝试按照此处的函数参数列表部分中的第二个示例进行操作,但似乎没有得到它:
template <typename obj, class ...C, typename... T>
void test2(const obj& obj_, T C...::* field_)
{
// ??
// and what about the function return parameter?
}
int main()
{
baz myObj;
test2(obj,&baz::d,&bar::b);
test2(obj,&baz::c);
}
有了这个,test2()
已经无法编译的定义。可以使用任何(最新)版本的 C++(尽管使用 MSVC)。出于测试目的,这里有一个关于 coliru 的完整程序。
解决方案
感谢Silvio 的回答,我能够解决它。利用 C++17,它还可以稍微短一些:
template <typename T, typename S, typename... Ss>
auto inline test2(const T& obj, S field1, Ss... fields)
{
if constexpr (!sizeof...(fields))
return obj.*field1;
else
return test2(obj.*field1, fields...);
}
解决方案
这需要c++17支持折叠表达式。
namespace utils {
template<class T>struct tag_t{ using type=T; };
template<class...Ts>
using last = typename std::tuple_element_t< sizeof...(Ts)-1, std::tuple<tag_t<Ts>...> >::type;
template<class Lhs, class F>
struct fold_invoker_t;
template<class Lhs, class F>
fold_invoker_t<Lhs, F> fold_invoker(Lhs&&lhs, F&& f);
template<class Lhs, class F>
struct fold_invoker_t {
Lhs lhs;
F f;
template<class Rhs>
auto operator*( Rhs&& rhs )&& {
return fold_invoker(std::forward<F>(f)(std::forward<Lhs>(lhs), std::forward<Rhs>(rhs)), static_cast<F>(f));
}
};
template<class Lhs, class F>
fold_invoker_t<Lhs, F> fold_invoker(Lhs&&lhs, F&& f){ return {std::forward<Lhs>(lhs), std::forward<F>(f)}; }
}
然后我们写:
template <typename Obj, class ...C, typename... T>
utils::last<Obj, T...> const& test2(const Obj& obj, T C::*... field)
{
auto get_member=[](auto&& elem, auto&& memptr)->decltype(auto){ return elem.*memptr; };
return (utils::fold_invoker( obj, get_member ) * ... * field).lhs;
}
并且都在这一行上展开。
不知道这是否适用于 MSVC 的 C++17 支持。
推荐阅读
- tensorflow - 冻结后存在 Batchnorm 层以从 DeeplabV3+ 模型进行推理,这样可以吗?
- firebase - 允许壁炉更新,但设置失败并显示“模拟设置被拒绝”
- amazon-web-services - 从 Jboss 到 AWS 云观察的参数化日志记录
- r - 如何在R中的同一图中绘制矩阵每一列的ACF
- python - Pandas 数据框围绕基础数据(不仅仅是它的显示方式)
- python - 将 Python 代码转换为 Matlab 脚本
- c++ - 比较 C++20 中的多态类型
- python - 使用或不使用枢轴来展平长数据帧的最佳方法
- python - 从nodejs运行python脚本时子进程退出代码1
- python - 列表作为 Python 类方法的输入