首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在`pair<Key、Value>`和`pair<const键、Value>`之间键入双关语

在`pair<Key、Value>`和`pair<const键、Value>`之间键入双关语
EN

Stack Overflow用户
提问于 2022-06-18 16:28:40
回答 1查看 129关注 0票数 5

相对问题,但是我想要一个没有任何运行时开销的解决方案。(因此,构建一个新的pair或使用std::variant并不是答案)

由于潜在的模板专业化,参考文献pair<K, V>pair<const K, V>并不相似,这意味着简单的reinterpret_cast会触发未定义的行为。

代码语言:javascript
复制
auto p1 = pair<int, double>{ 1, 2.3 };
auto& p2 = reinterpret_cast<pair<const int, double>&>(p1); // UB!

通过union进行类型双关在C中工作得很好,但在C++中并不总是合法的:

但是有一个例外(与C中的行为一致):

如果两个联合成员是标准布局类型,那么在任何编译器上检查它们的公共子序列都是很好的定义。

由于KeyValue可能不是standard-layout,并且可能有non-trivial析构函数,所以这里似乎不可能进行类型双关,尽管pair<Key, Value>pair<const Key, Value>的成员可以共享相同的生存期(当然是使用对齐断言)。

代码语言:javascript
复制
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));

我注意到了std::map::extractNode handle的保证。因此,我相信一些类似的行为(类型双关语或const_cast)确实存在于与Node handle相关的STL实现中。

libc++中,它似乎依赖于clang (不为数据成员优化)的特性,而不是标准。

libstdc++执行libc++,但没有刷新类型状态的std::launder

MSVC .非常令人惊讶..。而且提交历史太短,我找不到支持如此简单的混叠的任何理由。

这里有标准的方法吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-06-25 15:15:22

这是不可能的。node_handle的提案提到这是标准化的一个动机:

标准库存在的原因之一是编写客户端无法用可移植C++ (例如,>等)编写的不可移植和神奇的代码。这只是另一个例子。请注意,key成员函数是唯一需要此类技巧的地方,并且不需要对容器或对进行更改。

参考

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72670928

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档