gpt4 book ai didi

c++ - 用 C++ : legal or not? 重新解释这个

转载 作者:可可西里 更新时间:2023-11-01 16:36:42 26 4
gpt4 key购买 nike

这是一个有点深奥的问题,但我很好奇以下类扩展模式在现代 C++ 中是否合法(例如,不构成 UB)(出于所有意图和目的,我可以将讨论限制在 C+ +17 及更高版本)。

template<typename T>
struct AddOne {
T add_one() const {
T const& tref = *reinterpret_cast<T const*>(this);
return tref + 1;
}
};

template<template<typename> typename E, typename T>
E<T> const& as(T const& obj) {
return reinterpret_cast<E<T> const&>(obj);
}

auto test(float x) {
return as<AddOne>(x).add_one();
}

auto test1(int x) {
return as<AddOne>(x).add_one();
}

// a main() to make this an MVCE
// will return with the exit code 16
int main(int argc, const char * argv[]) {
return test1(15);
}

上面的代码是一个完整的例子,它在C++17模式下编译、运行并产生至少clang的预期结果。检查编译器资源管理器上的反汇编代码:https://godbolt.org/z/S3ZX2Y

我的解释如下:标准规定reinterpret_cast可以在任何类型的指针/引用之间进行转换,但是访问那里产生的引用可能是 UB(根据别名规则)。同时,将结果值转换回原始类型可以保证产生原始值。

基于此,仅重新获取对 float 的引用作为对 AddOne<float> 的引用不调用 UB。因为我们从不尝试访问该引用后面的任何内存作为 AddOne<float> 的实例,这里也没有UB。我们只使用该引用的类型信息来选择 add_one() 的正确实现。成员函数。该函数本身将引用转换回原始类型,因此同样没有 UB。本质上,此模式在语义上等同于此:

template<typename T>
struct AddOne {
static T add_one(T const& x) {
return x + 1;
}
};

auto test(float x) {
return AddOne<Int>::add_one(x);
}

我是对的还是我错过了什么?

将此视为探索 C++ 标准的学术练习。

编辑:这不是 When to use reinterpret_cast? 的拷贝因为那个问题不讨论类型转换this指针或使用 reinterpret_cast调度重新解释的类型。

最佳答案

不,这绝对不合法。出于多种原因。

第一个原因是,你有 *this取消引用 AddOne<int>*它实际上并不指向 AddOne<int> .该操作实际上不需要“在幕后”取消引用并不重要; *foo仅在 foo 时才合法指向兼容类型的对象。

第二个原因类似:你在 AddOne<int> 上调用一个成员函数这不是。您不访问任何 AddOne 也没有关系的(不存在的)成员:函数调用本身是对对象值的访问,违反了严格的别名规则。

关于c++ - 用 C++ : legal or not? 重新解释这个,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54957577/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com