c++ const_cast不适用于std::remove_reference [closed]

ssm49v7z  于 2023-05-30  发布在  其他
关注(0)|答案(2)|浏览(150)

**已关闭。**此问题为not reproducible or was caused by typos。目前不接受答复。

此问题是由打印错误或无法再重现的问题引起的。虽然类似的问题在这里可能是on-topic,但这个问题的解决方式不太可能帮助未来的读者。
2天前关闭。
Improve this question
这里有一个最小的例子来说明我想达到的目标

#include <array>

int main() {
    std::array<int, 5>* arr = new std::array<int, 5>{}; // no fill
    int** temp = new int*;

    for (const auto& e : *arr) {
        // some code that uses e...
        *temp = const_cast< std::remove_reference<decltype(e)>* >(&e); //error
        *temp = const_cast< int* >(&e); //ok
    }

    **temp = 22;
}

我需要用decltype访问e的类型,并指向e,所以我从decl类型中删除了引用,并用指针声明了它。
但它不工作,并将std::remove_reference视为类invalid 'const_cast' from type 'const int*' to type 'std::remove_reference<const int&>*'
我该怎么解决?

zbq4xfa0

zbq4xfa01#

decltype(&e)给出了&e表达式的类型,并将值类别转换为匹配的引用限定。
所以强制转换const_cast<decltype(&e)>(&e)不做任何事情。它将类型为int* const*和值类别prvalue的&e转换为类型int* const*,即const_cast<decltype(&e)>(&e)是一个表达式,它本身具有类型int* const*和值类别prvalue,结果与&e具有相同的值。
如果要删除const,则需要强制转换为int**,而不是int* const*。您需要从类型中删除const,例如使用std::remove_cvref_t,你可以从e声明的类型中删除引用和const限定(这是decltype(e)将返回的):

*temp = const_cast<std::remove_cvref_t<decltype(e)>*>(&e);

然而,这是危险的。有人可能会将*arr更改为不可修改的对象,然后编译器不会再给予你任何警告或错误,因为const_cast会抑制它。然后你会有未定义的行为。
如果你需要引用在大多数情况下都是const,最好从一个非const引用开始,然后在应该是const的范围内添加一个const引用:

for (auto& e_modifiable : *arr) {
    {
        const auto& e = e_modifiable;
        // some code that uses e...
    }
    // *temp was probably unintended. It has the wrong type and
    // temp is uninitialized. However `**temp = 22;` also is UB
    // because all elements of the array are null pointers.
    temp = &e_modifiable; // error
}

另外,请注意您的问题下有关您的代码的其他有效注解。总而言之,我怀疑你使用了太多的指针和new,尽管没有足够的上下文来确切地知道这是什么。

tkclm6bt

tkclm6bt2#

首先,当你可以使用std::array::fill时,没有必要使用std::array::fill

//------------------------------------------------vv-->use zero initialization
std::array<int*, 5>* arr = new std::array<int*, 5>{}; 
//no need to use fill here

现在来看看错误:
为什么不管用?
因为a)您使用const_cast删除const是不正确的。另外,您正在将&e转换为它已有的类型。如果需要的话,您可以完全省略演员表。
更重要的是,即使没有低级常量,并且我们只有int**而不是int* const*,仍然不能将int**类型的表达式分配给int*类型的表达式,因为两者之间没有转换(显式或隐式)。
还要注意,temp未初始化,因此*tempundefined behavior

相关问题