掩蔽结构名称
Posted
技术标签:
【中文标题】掩蔽结构名称【英文标题】:Masking Structure Name 【发布时间】:2020-07-10 01:21:28 【问题描述】:我正在尝试像这样屏蔽结构名称:
#define cat_val(l, r) l##r
#define name_mask cat_val(exception_, __COUNTER__)
using i_dont_show_in_rtti = struct name_mask
// ...
;
void test()
throw i_dont_show_in_rtti;
这有效,但只能在文件中单独使用。如果我包含一个完成此操作的文件,我会遇到命名冲突(因为 __COUNTER__
会重置每个文件)。
我还有哪些其他选择?是否有另一种方法可以改变一个名称,使其难以理解但又独一无二,而不会让我的代码变得不合理地丑陋?
【问题讨论】:
你只是想throw
每次都唯一的类型吗?
@cigien 不,我希望它是同一类型,以便我可以抓住它。但我不希望实际名称显示在 RTTI 中,所以我希望它只是一个通用的 exception_55
unintelligable yet unique
我还会在需求列表中添加“易于维护者可逆”。如果有人报告看到exception_55
,您 应该很容易追踪到实际来源。基于全局计数器的方案不一定会那么容易。
您想要屏蔽名称的原因是什么?为了找到它们,您可以在命名空间中管理您的异常。
@BerndBaumanns 静态分析阻力
【参考方案1】:
在完全标准的 C++14 中可以做到这一点。
#include <cstdlib>
template <std::size_t N>
constexpr std::size_t ct_hash(const char (&str)[N])
std::size_t hash = 0;
for (std::size_t i = 0; i < N; ++i)
hash = (hash << 7) + (str[i] * str[i]); // just an example
return hash;
template <std::size_t ... hashes>
struct mangled;
// don't have to use all of these, it's just an example. may use __COUNTER__ instead of __LINE__.
#define HIDE_STRUCT(S) \
using S = struct mangled<ct_hash(__FILE__), __LINE__, ct_hash(__DATE__), ct_hash(__TIME__), ct_hash(#S)>; \
template <> struct mangled<ct_hash(__FILE__), __LINE__, ct_hash(__DATE__), ct_hash(__TIME__), ct_hash(#S)>
HIDE_STRUCT(foo)
int a;
;
HIDE_STRUCT(bar)
int a; char b;
;
void test()
throw foo;
void test2()
throw bar;
如果您担心可能的哈希冲突,您可以对字符串进行可逆加密而不是对其进行哈希处理,但这可能需要 C++20 宽松的非类型模板参数(以便您可以对加密字符串进行参数化)。您必须编写一个编译时加密函数。
【讨论】:
这在 rdata 中是什么样子的? 我很确定您关于使用__COUNTER__
而不是__LINE__
的评论不正确。如果这是在头文件中定义的,那么 __COUNTER__
对于包括它在内的每个翻译单元都可能不同——这将导致一个具有不同名称的新定义,除非它是一个巨大的文件,否则无法在 API 上使用跨度>
实际上,散列 __DATE__
和 __TIME__
也可以做同样的事情——因为不同的翻译单元可能在不同的时间构建(增量构建)
@Human-Compiler 是的,如果您在多个 TU 中需要它,则不应使用日期和时间。
关键是要获得可以跨不同翻译单元工作的东西。尽管这确实具有仅对名称进行哈希处理并将其用作模板参数的基本思想。以上是关于掩蔽结构名称的主要内容,如果未能解决你的问题,请参考以下文章