最近我正在做一些检索结构数据成员类型的工作。当我探索、研究和测试想法时,我发现了这颗珍珠:template<int N> struct tag{};template<typename T, int N>struct loophole_t {friend auto loophole(tag<N>) { return T{} ; };};自动漏洞(tag<0>);sizeof(loophole_t<std::string, 0>);===> std::is_same< std::string, decltype( loophole(tag<0>{} ) ) >:: 值; <=== 有趣。我在创建 struct reader 以检测结构的数据成员类型时非常痛苦。而且它受到了痛苦的限制:只有文字类型、预建类型列表等。有了它,一切皆有可能。经过一些编译器的斗争,我想出了一个优雅的十行代码头,它可以从一个数据结构(有一定的限制)用 C++ 创建类型列表,没有固定类型列表。这是它可以做什么的简短示例:使用 wndclass_tlist = loophole_ns::as_type_list< WNDCLASS >;Resulting type list (Visual Studio 2017): 0. unsigned int 1. __int64 (__cdecl*)(struct HWND__ * __ptr64, unsigned int ,unsigned __int64,__int64) 2. int 3. int 4. struct HINSTANCE__ * __ptr64 5. struct HICON__ * __ptr64 6. struct HICON__ * __ptr64 7. struct HBRUSH__ * __ptr64 8. wchar_pt * __ptr64 const 类型漏洞基本上允许我们将某种类型存储到“变量”中,然后再读回来!它非常强大。更多示例:我们可以将结构转换为 luple:我设计的轻量级元组,具有跨编译器稳定布局的优势(至少就我测试而言):
结构数据{浮动一个; std::string b;};using data_tlist = loophole_ns::as_type_list< data >;using data_luple = luple< data_tlist >;data d{ 1.f, "Hello World!" };auto& l = reinterpret_cast< wndclass_luple& >( d ); //我知道你的感受)get< std::string >(l) = "Welcome, New World!" luple_do( l, []( auto& value ) { std::cout << value << "\n" ; } );如果您想了解更多有关它的工作原理及其局限性的信息,请查看代码。我在 GitHub 存储库中提供了类型漏洞和 luple 的完整注释源代码。它适用于所有三个主要编译器。您可以在 godbolt.org 上找到使用类型漏洞的数据成员类型检测器的更简洁示例(一个稍微不同的版本最初由 Reddit 上名为 jguegant 的用户提供)。 Sasha Sobol 提出了一个例子(在 Coliru 在线),它可以在编译时为类型分配唯一的 ID(它依赖于实例化顺序)。如果你不习惯阅读源代码,那么 Reddit 上的一些好人 (render787) 做了一个详细的评论,很好地观察了这个漏洞如何允许获取结构数据成员类型信息。到目前为止,我还没有检查这是否违反了标准。因此,非常欢迎 C++ 标准专家。在 Twitter 上第一个做出回应的是 Simon Brand,他指出了一个缺陷报告 2118。在 Twitter 上关注我以获取有关我的新文章(主要是编程和计算机图形)的更新。
我应该为所有其他 C++ 领导者创建一个模因,例如 Scott Meyers、Stephan T. Lavavej、Alisdair Meredith、Howard Hinnant 以及委员会中的每个人以及其他为 C++ 做出贡献的人。