C++ 从std::tuple提取方法签名的类型
我正在寻找一种方法来提取C++ 从std::tuple提取方法签名的类型,c++,c++17,template-meta-programming,stdtuple,parameter-pack,C++,C++17,Template Meta Programming,Stdtuple,Parameter Pack,我正在寻找一种方法来提取std::tuple的类型来定义方法签名。以以下(人为的)例子: 模板 甲级 { 公众: 类型def RetT ReturnType; typedef std::元组ArgTypes; 回收剂量测定法(ArgsT…args) { //没有什么意义,但这只是一个例子 返回(RetT)printf(args…); } }; 模板 A级适配器; //只需按原样传递参数即可 模板 类AAdapter、RetT、ArgsT…>:public A{}; //如果RetT是float,
std::tuple
的类型来定义方法签名。以以下(人为的)例子:
模板
甲级
{
公众:
类型def RetT ReturnType;
typedef std::元组ArgTypes;
回收剂量测定法(ArgsT…args)
{
//没有什么意义,但这只是一个例子
返回(RetT)printf(args…);
}
};
模板
A级适配器;
//只需按原样传递参数即可
模板
类AAdapter、RetT、ArgsT…>:public A{};
//如果RetT是float,则添加额外的第一个参数
模板
A级适配器:公共A{};
模板
B类
{
公众:
类型定义A适配器A适配器;
//这需要与aaAdapter::doSomething()具有相同的方法签名(返回类型和参数类型)
模板
typename AAdapter::ReturnType doSomething(
typename std::tuple_元素::type…args
) {
返回a.doSomething(参数…);
}
公众:
a适配器a;
};
int main(int argc,字符**argv)
{
//我希望能够删除和下面的。
B b1;
b1.剂量测量(“两个值:%d,%d\n”,1,2);
B b2;
b2.doSomething(“三个值:%s,%d,%d\n”,“一个字符串”,1,2);
返回0;
}
考虑AAAdapter更改、添加或删除参数类型的方式。基本上,我希望B::doSomething()
简单地重定向到B::AAdapter::doSomething()
,因此我希望这两个方法具有完全相同的签名。问题是:如何从B
内部获取B::AAdapter::doSomething()
的参数类型
我在上面的代码中对B::doSomething()
的定义是我所做的最远的定义:我正在键入一个std::tuple
,其中包含A
中的参数类型,这样我就可以将它们解压回B
中的参数包。不幸的是,使用上述方法,在调用B::doSomething()
时,我仍然需要手动提供索引…
模板参数。当然,一定有一种方法可以让这些索引…
参数自动从元组的大小推断出来。我曾考虑过使用std::make_integer_sequence
的方法,但这需要我为序列本身定义一个额外的方法参数(它不能是最后一个具有默认值的参数,因为在参数包之后不允许有其他参数)
有没有什么方法可以做到这一点,有没有std::tuple?需要C++17的解决方案就可以了
编辑1:
我现在意识到,我可以通过让B
从AAdapter
继承而不是让AAdapter
对象作为成员来规避我的特定应用程序中的问题,但我仍然想知道如何解决问题而不必这样做
编辑2:
也许可以提供一些关于为什么AAdapter
存在以及我想要实现什么的附加信息。我正在围绕一个现有的C API实现一种包装类,它实际上需要在另一个进程RPC风格中调用。因此,如果用户希望在远程进程中调用C函数,他们将在本地调用我的包装器类中的相应方法,该方法处理所有RPC内容,如类型转换、实际的远程调用和其他丑陋的细节。在上面的代码中,这个包装类由B
表示。现在,我的包装器方法签名通常与C函数的签名不完全相同。例如,包装器可能具有std::string\u view
而不是C函数具有的一对const char*、size\u t
。出于此处不重要的原因,还需要有一个输出参数(指针),其中C函数有时有一个返回值
为了不必定义两个单独的方法签名(实际上是三个)并编写代码来转换每个方法的参数,我只将其中一个签名作为模板参数
RetT,ArgsT…
传递给B
。然后,签名转换类(AAdapter
,在上面的示例中)应用有关如何通过添加参数、更改其类型等从第一个签名自动生成第二个签名的规则A
将保存生成的签名,B
将保存我最初提供的签名。但是,我希望B
提供签名为A
的invoke()
方法,从而对用户完全隐藏A
和整个方法签名。这就是为什么我需要从B
中访问A
的模板参数类型,以及为什么我不能简单地删除中间类aaadapter
这演示了如何从元组中获取具有参数类型的函数:
#include <iostream>
#include <tuple>
#include <utility>
template <
typename ArgTuple
>
class B_Class {};
template <typename... ArgTypes>
class B_Class<std::tuple<ArgTypes...> > {
public:
static void b(
ArgTypes...
) {
std::cout << "successful call" << std::endl;
}
};
int main() {
using ArgTypes = std::tuple<int, char, float, double>;
int i; char c; float f; double d;
B_Class<ArgTypes>::b(i, c, f, d);
}
#包括
#包括
#包括
模板<
typename参数组
>
B_类{};
模板
B班{
公众:
静态空隙b(
ArgTypes。。。
) {
std::cout这演示了如何从元组获取具有参数类型的函数:
#include <iostream>
#include <tuple>
#include <utility>
template <
typename ArgTuple
>
class B_Class {};
template <typename... ArgTypes>
class B_Class<std::tuple<ArgTypes...> > {
public:
static void b(
ArgTypes...
) {
std::cout << "successful call" << std::endl;
}
};
int main() {
using ArgTypes = std::tuple<int, char, float, double>;
int i; char c; float f; double d;
B_Class<ArgTypes>::b(i, c, f, d);
}
#包括
#包括
#包括
模板<
typename参数组
>
B_类{};
模板
B班{
公众:
静态空隙b(
ArgTypes。。。
) {
标准::cout
问题的核心是将元组转换为参数包
可能元组类型不是模板参数?在这种情况下,有一个简单的继承解决方案:
#包括
#包括
#包括
模板
结构BImpl{
typedef std::tuple tuple_type;
//也许你会从一些类模板中得到一个元组类型。假设结果是“tuple\u type”。
//要求:'tuple_type'=std::tuple
//要求:'tupl