[英]I would like to deduce a type in C++ template, from a pointer to a member function
简洁版本:
不必总是输入:
auto function_pointer = &decorator<int, Foo, void &Foo::bar(int)>
我希望能够写
auto function_pointer = &decorator<void &Foo::bar(int)>
从<void &Foo::bar(int)
>中自动提取int
和Foo
位置。
对于初学者,我有:
map<string, Object*> all_object_instances;
class Object {
public:
Object(const string &name) { all_object_instances[name]=this; }
virtual ~Object() { all_object_instances.erase(name); }
};
class Foo : public Object {
public:
Foo(const string &name) : Object(name) {}
void bar(int);
};
我需要一个函数,该函数将以某种修饰方式调用Foo :: bar(int) ,所以我这样写:
template <class Arg, class C, void C::*T(Arg)>
void decorator(const string &name, const string &s_arg)
{
Arg a = my_convert(s_arg);
C* c = dynamic_cast<C*>(all_object_instances[name]);
(c->*T)(a);
}
所以我的主要代码必须看起来像这样:
new Foo("MyFoo");
....
auto saved_f = &decorator<int, Foo, void &Foo::bar(int)>;
....
saved_f("MyFoo", "123");
....
delete all_object_instances("MyFoo") // for symmetry
如果我只有一个模板参数,那就更好了:
saved_f = &decorator<void &Foo::bar(int)>;
并从参数中导出'Foo'和'int' :
template <TEMPLATE MAGIC>
void decorator(const string &name, const string &s_arg)
{
typedef ARG_MAGIC ARG;
typedef CLASS_MAGIC C;
Arg a = my_convert(s_arg);
C* c = dynamic_cast<C*>(all_object_instances[name]);
(c->*T)(a);
}
有没有这样的东西?
将函数作为参数传递将允许它被调用。 它可以简单地通过模板参数推导来推导。
在下面的示例中,我刚刚添加了一些通用性,将参数通过std::invoke
传递,该参数可以执行自动指针到成员的调用。
template<class R,class C,class... Args>
auto get_class_type(R(C::*)(Args...))->C;
template<class F>
auto decorator(F f) {
return [f=move(f)](auto const& name, auto const& arg) {
using C=decltype(get_class_type(f));
return std::invoke(move(f),
dynamic_cast<C*>(all_object_instances[name]),
my_convert(arg)
);
};
}
现在减少到:
auto saved_f = decorator(&Foo::bar);
saved_f("MyFoo", "123");
这需要std::invoke
的C ++ 1y兼容编译器,可以在<functional>
找到。 如果这不能为您编译,只需将其更改为:
auto c = dynamic_cast<C*>(all_object_instances[name]);
return (c->*move(f))(my_convert(arg));
如果您的目标是让template参数成为编译时间常数,那也是可能的。 在这种情况下,你将不得不使用宏,并传递一个integral_constant
来decorator
:
#define decorator(mem_f) decorator_impl( integral_constant<decltype( mem_f ), mem_f>{} )
然后从类型中提取值:
template<class I>
auto decorator_impl( I ) {
auto constexpr f = I::value;
// same code as before...
}
在c ++ 17中,您应该能够编写:
template <auto m>
void decorator(const string &name, const string &s_arg);
具有所需的语法:
auto saved_f = &decorator<void &Foo::bar(int)>
代替
template <typename M, M m>
void decorator(const string &name, const string &s_arg);
带有语法
auto saved_f = &decorator<decltype(&Foo::bar), &Foo::bar>;
或您的版本。
然后,您需要一些函数特征来检索类和返回类型,例如:
template <typename> struct method_traits;
template <typename Ret, typename Class, typename ... Args>
struct method_traits<Ret (Class::*)(Args...)>
{
using ret_type = Ret;
using classe_type = Class;
using args_type = std::tuple<Args...>;
};
所以最后:
template <auto m>
void decorator(const string &name, const string &s_arg)
{
using C = typename method_traits<decltype(m)>::class_type;
using Arg = std::tuple_element_t<0, typename method_traits<decltype(m)>::args_type>;
Arg a = my_convert(s_arg);
C* c = dynamic_cast<C*>(all_object_instances[name]);
(c->*T)(a);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.