使用C++模板编程提取任意结构的字段类型

top*_*pin 5 c++ templates struct metaprogramming variadic-templates

如果我定义一个具有任意数据类型的结构,例如:

struct custom_type {
    int a;
    float b;
    char c; 
    float *d; // etc...
};
Run Code Online (Sandbox Code Playgroud)

是否存在使用模板编程(C++)来提取该结构的字段类型并在编译时将它们映射到某些特定于类型的代码处理程序的常见模式?

一些上下文:我正在创建一个 API,允许客户定义自己的任意自定义类型,并且仍然允许它们与我用于管理和内省这些类型、执行自动内存管理和其他内务处理的底层系统集成。

“包装”模板或其他机制将允许这种集成,而底层系统无需了解有关定义自定义类型的头文件的任何信息。从客户端的角度来看,代码以正常方式访问结构,但模板允许对结构中的每个字段进行通用处理。

谢谢。

Jul*_*ius 2

您描述的行为称为反射。支持此功能的 C++ 语言功能非常有限(目前)。然而,通过一些技巧,可以实现一定程度的反思。

Antony Polukhin 的 Boost.PFR(精确且平坦的反射)就是一个例子。PFR 自 2020 年 12 月起成为官方 boost 库(boost 1.75.0),但根据其文档,它是一个

不依赖于 Boost 的仅标头库。

以下是自述文件中的一个示例

#include <iostream>
#include <string>

#include "boost/pfr.hpp"

struct some_person {
    std::string name;
    unsigned birth_year;
};

int main() {
    some_person val{"Edgar Allan Poe", 1809};

    std::cout << boost::pfr::get<0>(val)                // No macro!
        << " was born in " << boost::pfr::get<1>(val);  // Works with any aggregate initializables!

    std::cout << boost::pfr::io(val);                   // Outputs: {"Edgar Allan Poe", 1809}
}
Run Code Online (Sandbox Code Playgroud)

在限制和配置一章中,文档指出至少需要 C++14,但建议至少 C++17。一个重要的要求是

T 必须是可聚合初始化的,且没有空基类

一些基础技术在CppCon 2016 录制的演讲中进行了解释,演讲标题为“没有宏、标记或外部工具的 C++14 反射..”