简短版本:
而不是总是输入:
auto function_pointer = &decorator<int, Foo, void &Foo::bar(int)>
我希望能够写出
auto function_pointer = &decorator<void &Foo::bar(int)>
从int
&gt;自动提取Foo
和<void &Foo::bar(int)
。
对于初学者我有:
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);
}
有没有这样的东西?
答案 0 :(得分:0)
将函数作为参数传递将允许调用它。它可以通过模板参数推导简单推导出来。
在下面的示例中,我刚刚添加了一些通用性,通过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));
如果你的目标是让模板参数成为编译时常量,那也是可能的。在这种情况下,您必须使用宏并将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...
}
答案 1 :(得分:-1)
在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);
}