带有const引用的Std::remove_const

std::remove_const with const references

本文关键字:const remove 引用 带有 Std      更新时间:2023-10-16

为什么std::remove_const不将const T&转化为T& ?这个无可否认相当做作的例子证明了我的问题:

#include <type_traits>
int main()
{
    int a = 42;
    std::remove_const<const int&>::type b(a);
    // This assertion fails
    static_assert(
        !std::is_same<decltype(b), const int&>::value,
        "Why did remove_const not remove const?"
    );
    return 0;
}

上面的情况很容易修复,所以对于上下文,想象如下:

#include <iostream>
template <typename T>
struct Selector
{
    constexpr static const char* value = "default";
};
template <typename T>
struct Selector<T&>
{
    constexpr static const char* value = "reference";
};
template <typename T>
struct Selector<const T&>
{
    constexpr static const char* value = "constref";
};
int main()
{
    std::cout
        << Selector<typename std::remove_const<const int&>::type>::value
        << std::endl;
    return 0;
}

在上面的示例中,我希望显示reference,而不是constref

std::remove_const删除顶级 const -资格。在相当于T const&const T&中,限定条件不是顶级的:事实上,它并不适用于引用本身(这将是毫无意义的,因为根据定义,引用是不可变的),而是适用于被引用的类型。

c++ 11标准第20.9.7.1段中的表52规定,关于std::remove_const:

成员typedef type应该与T命名相同的类型,除了任何顶级 const限定符已被删除。[示例: remove_const<const volatile int>::type求值为volatile int, remove_const<const int*>::type求值到const int*。- 结束示例]

为了剥离const,您首先必须应用std::remove_reference然后应用std::remove_const,然后(如果需要)应用std::add_lvalue_reference(或任何适合您的情况)。

注意:正如Xeo在评论中提到的,您可以考虑使用别名模板(如Unqualified)来执行前两个步骤,即剥离引用,然后剥离const -(和volatile-)资格。