Hed*_*ede 6 c++ undefined-behavior language-lawyer unnamed-namespace
我一直在使用一个肮脏的技巧,我使用未命名的名称空间来为每个文件指定不同的行为(用于单元测试)。感觉它不应该被明确定义,但它适用于过去六年发布的每个主要编译器。
我首先在匿名名称空间中前向声明一堆类:
namespace {
class context_check;
class context_block;
class register_test;
} // namespace
Run Code Online (Sandbox Code Playgroud)
然后我声明一个类并创建这些类friend:
struct test_case
{
// ...
};
class context {
// ...
private:
// TODO: this feels like ODR-violation...
friend class context_check;
friend class context_block;
friend class register_test;
private:
void add_test(test_case&& test)
{
// ...
}
// ...
};
Run Code Online (Sandbox Code Playgroud)
在每个 cpp 文件中,我都有以下声明(为了简单起见,我将它们复制并粘贴到此处,但实际上我在标头中声明了未命名命名空间的内容):
// A.cpp
namespace {
extern context file_context;
class register_test {
public:
register_test(const char* test_name, test_case&& test)
{
file_context.add_test(std::move(test));
}
};
} // namespace
register_test register_test_1( test_case{"test1"} );
Run Code Online (Sandbox Code Playgroud)
// B.cpp
namespace {
extern context file_context;
class register_test {
public:
register_test(const char* test_name, test_case&& test)
{
file_context.add_test(std::move(test));
}
};
} // namespace
register_test register_test_2( test_case{"test2"} );
Run Code Online (Sandbox Code Playgroud)
那么每个 TU 都有自己的 等定义register_test。context_check这个定义明确吗?感觉应该是UB。。。
似乎违反了 ODR 要求的以下条件,如https://en.cppreference.com/w/cpp/language/definition中所述:
程序中可以有多个以下各项的定义:类类型、[...],只要满足以下所有条件:
- [...]
- 每个定义中的名称查找都会找到相同的实体(在重载解析之后),除了 [...]
没有任何异常是相关的,并且查找例如context_checkin friend class context_check;,它是 定义的一部分context,会找到一个内部链接实体,如果定义包含在多个翻译单元中,则该实体不能相同。
该标准的实际相应规则可以在例如C++20 后草案的[basic.def.odr]/13.9中找到。
| 归档时间: |
|
| 查看次数: |
145 次 |
| 最近记录: |