试图避免为x参数量重载我的函数。
//T.. Types,C Class,R Return type
template<typename R = void,class C,typename T1,typename T2>
R callClassFunction(C& classname,void (C::*func)(T1,T2), void** myd)
{
return (classname.*func)(*((T1*)myd[0]), *((T2*)myd[1]));
}
是否可以使用可变参数模板执行此操作?
由于数据数组,我无法弄清楚正确的语法。
答案 0 :(得分:0)
是否可以使用可变参数模板执行此操作?
如果我理解你想要什么,你正在寻找以下内容
template<typename R, class C, typename ... Ts1, typename ... Ts2>
R callClassFunction (C & classname, R (C::*func)(Ts1...), Ts2 && ... as)
{ return (classname.*func)(std::forward<Ts2>(as)...); }
我的意思是:
1)返回类型R
可以从方法指针推导出来,不需要将其默认为void
2)参数的可变参数列表(Ts1...
)也可以从方法指针推导出来
3)对于传递给callClassFunction()
的以下参数,将传递给func()
,我建议使用不同的可变参数类型列表Ts2...
,因为不需要Ts1...
等于Ts2...
;只需将Ts2...
类型转换为Ts1...
类型;这样您就可以将"123"
(char const *
或char[]
),而不一定是std::string("123")
传递给等待std::string
的方法
以下是一个完整的工作示例
#include <string>
#include <type_traits>
struct foo
{
long bar (std::string const & a, int b, char c)
{ return a.size() + b + c; }
void baz (std::string const &, int, char)
{ }
};
template<typename R, class C, typename ... Ts1, typename ... Ts2>
R callClassFunction (C & classname, R (C::*func)(Ts1...), Ts2 && ... as)
{ return (classname.*func)(std::forward<Ts2>(as)...); }
int main ()
{
foo f;
auto r { callClassFunction(f, &foo::bar, "123", 4, '5') };
static_assert( std::is_same<long, decltype(r)>{}, "!" );
callClassFunction(f, &foo::baz, "123", 4, '5');
}
- 编辑 -
OP问
如果我想保留
进行投射,该怎么办?void*
数组并使用Ts1
类型从void*
我发现它非常危险但是......如果使用如下定义模板
template <typename T0, typename...>
using only_first = T0;
您可以使用它在callClassFunction()
void *
个Ts1...
参数列表中强加Ts...
(重命名为Ts2...
,因为不再有template<typename R, class C, typename ... Ts>
R callClassFunction (C & classname, R (C::*func)(Ts...),
only_first<void *, Ts> ... as)
)
Ts...
并且,在函数体中,您可以使用void *
将Ts...
指针转换为return (classname.*func)(*static_cast<Ts*>(as)...);
指针
#include <string>
#include <type_traits>
struct foo
{
long bar (int a, double b, char c)
{ return a + b + c; }
void baz (int, double, char)
{ }
};
template <typename T0, typename...>
using only_first = T0;
template<typename R, class C, typename ... Ts>
R callClassFunction (C & classname, R (C::*func)(Ts...),
only_first<void *, Ts> ... as)
{ return (classname.*func)(*static_cast<Ts*>(as)...); }
int main ()
{
foo f;
int i { 1 };
double d { 2.0 };
char c { '3' };
auto r { callClassFunction(f, &foo::bar, (void*)&i, (void*)&d, (void*)&c) };
static_assert( std::is_same<long, decltype(r)>{}, "!" );
callClassFunction(f, &foo::baz, (void*)&i, (void*)&d, (void*)&c);
}
我再说一遍:我发现这非常危险,我很害怕这个解决方案。
但如果你真的想...以下是经过修改的完整工作示例
diff
答案 1 :(得分:0)
这应该有效:
template <typename R, class C, typename... Ts, size_t... Is>
R impl(C& instance, R (C::*func)(Ts...), void** data, index_sequence<Is...>)
{
return (instance.*pmf)(*static_cast<Ts*>(data[Is])...);
}
template <typename R, class C, typename... Ts>
R callClassFunction(C& instance, R (C::*func)(Ts...), void** data)
{
return impl(instance, func, data, make_index_sequence<sizeof...(Ts)>{});
}
index_sequence
是C ++ 14,但可以在C ++ 11中实现,你可以在SO上找到很多实现。
关键是,我们建立了这个整数序列,我们可以使用它们来索引你的void*
。该序列与Ts
的大小相同,因此我们可以将Ts
和Is
解包在一起。
请注意,这仅适用于指向成员函数的非const
指针。您需要再次执行此操作以获取指向const
成员函数的指针。
此外,如果成员函数采用参考,这不会很有效 - 您需要稍微不同的操作。我将这作为练习留给读者。