zjy*_*qs 5 c++ language-lawyer type-punning
一个相对的问题,但我想要一个没有任何运行时开销的解决方案。(所以构建一个新的pair或使用std::variant不是答案)
由于潜在的模板专业化,参考文献已经说过pair<K, V>和pair<const K, V>不相似,这意味着简单的reinterpret_cast会触发未定义的行为。
auto p1 = pair<int, double>{ 1, 2.3 };
auto& p2 = reinterpret_cast<pair<const int, double>&>(p1); // UB!
Run Code Online (Sandbox Code Playgroud)
类型双关union在 C 中工作得很好,但在 C++ 中并不总是合法的:
但有一个例外(与 C 中的行为一致?):
由于KeyandValue可能不是并且standard-layout可能有non-trivial析构函数,因此这里的类型双关似乎是不可能的,尽管pair<Key, Value>和的成员pair<const Key, Value>可以共享相同的生命周期(当然带有对齐断言)。
template <typename Key, typename Value>
union MapPair {
using TrueType = pair<Key, Value>;
using AccessType = pair<const Key, Value>;
static_assert(
offsetof(TrueType, first) == offsetof(AccessType, first)
&& offsetof(TrueType, second) == offsetof(AccessType, second)
&& sizeof(TrueType) == sizeof(AccessType)
);
TrueType truePair;
AccessType accessPair;
~MapPair() {
truePair.~pair();
}
// constructors for `truePair`
};
//...
auto mapPair = MapPair<NonTrivialKey, NonTrivialValue>{/*...*/};
// UB? Due to the lifetime of `truepair` is not terminated?
auto& accessPair = reinterpret_cast<pair<const NonTrivialKey, NonTrivialValue>&>(mapPair);
// still UB? Although objects on the buffer share the same constructor/destructor and lifetime
auto* accessPairPtr = std::launder(reinterpret_cast<pair<const NonTrivialKey, NonTrivialValue>*>(&mapPair));
Run Code Online (Sandbox Code Playgroud)
我注意到调用 时std::map::extract保证不会复制或移动任何元素,并且用户定义的规范化std::pair会在操作 时导致 UBNode handle。所以我相信一些类似的行为(类型双关或const_cast)确实存在于与 相关的 STL 实现中Node handle。
在 中libc++,它似乎取决于clang(不针对数据成员进行优化)的特征,而不是标准。
libstdc++做了与 类似的工作libc++,但没有std::launder刷新类型状态。
MSVC是......非常令人惊讶......并且提交历史太短,我找不到任何理由来支持如此简单的别名......
这里有标准方法吗?
| 归档时间: |
|
| 查看次数: |
194 次 |
| 最近记录: |