成员变量指针的函数参数包
function parameter pack for member variable pointer
我正在尝试通过嵌套成员指针访问结构中的变量:
#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的完整程序。
溶液
多亏了西尔维奥的回答,我才能够解决它。利用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++模板非常喜欢的"把它扔到墙上,看看有什么粘住"的方法。
template <typename T>
auto test2(const T& obj) -> T {
return obj;
}
template <typename T, typename S, typename... Ss>
auto test2(const T& obj, S field1, Ss... fields)
-> decltype(test2(obj.*field1, fields...)) {
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 支持。
相关文章:
- 将可变参数函数的参数封装在类实例中
- QML 使用带有参数C++函数
- 使用可变参数函数作为模板参数
- 如何在C++中伪造虚拟可变参数函数模板?
- 为什么可变参数函数不适用于模板
- C++ std::functional 中的可变参数函数模板
- 可变参数函数指针的定义对于VxWorks spyLib来说不清楚
- 使用可变参数函数覆盖具有不同函数签名的虚函数
- 考虑引用和常量的可变参数函数包装器
- 使用可变参数函数将整数和/或整数数组放入单个 int 数组中
- 在可变参数函数中转发特定范围的参数
- 通过引用传递参数;函数返回类型是否必须为 VOID?
- 使用带有一个参数函数的递归找到数字的平方
- 可变参数函数模板不能很好地使用 std::function 作为参数
- 多个可变参数函数的单个模板参数包?
- 参数数据类型未知的可变参数函数
- 可变参数函数参数包扩展
- 使用模板可变参数函数将多个参数传递给另一个函数
- 对可变参数函数的递归调用的链接器错误
- 通过像printf这样的可变参数函数传递一个带有常量字符*转换函数的类