带有const引用的std :: remove_const

时间:2013-04-08 19:19:21

标签: c++ templates c++11 std

为什么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

1 个答案:

答案 0 :(得分:14)

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

C ++ 11标准第20.9.7.1段中的表52规定了std::remove_const

  

除了T之外,成员typedef类型的名称应与remove_const<const volatile int>::type相同   已删除任何顶级 const限定符。   [示例volatile int评估为   remove_const<const int*>::type,而const int*评估   到const。 - 结束示例]

要剥离std::remove_reference,您首先必须应用std::remove_const然后应用std::add_lvalue_reference,然后(如果需要)应用{{1 (或在你的情况下适当的任何东西)。

注意:在评论中提及Xeo时,您可以考虑using an alias template such as Unqualified执行前两个步骤,即删除引用,然后删除{{ 1}} - (和const)资格。