25

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

4

1 回答 1

25

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

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,您首先必须 apply std::remove_reference然后apply std::remove_const,然后(如果需要) apply std::add_lvalue_reference(或任何适合您的情况)。

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

于 2013-04-08T19:26:05.093 回答