2013-04-08 54 views
14

为什么std::remove_const不能将const T&转换为T&?这个不可否认的虚构的例子演示了我的问题:std :: remove_const与常量引用

#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

+0

请记住,没有这样的东西作为const引用,只有const的引用。 – xaxxon 2016-07-14 09:19:17

回答

13

std::remove_const删除顶级const -qualifications。在const T&(相当于T const&)中,限定条件不是顶层的:实际上,它不适用于引用本身(因为引用根据定义是不可变的,所以引用本身没有意义),而是适用于引用类型。

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

的构件的typedef类型应命名相同类型T除了 任何顶层常量 - 限定符已被删除。 [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在注解中提到的,可以考虑using an alias template such as Unqualified执行前两个步骤,即除掉那些参考,然后剥去该const - (和volatile-)资格。

+1

前两个通常在“不合格”别名下组合在一起。 – Xeo 2013-04-08 19:40:38

+0

@Xeo:编辑,谢谢。 – 2013-04-08 19:44:43

+0

啊,我现在明白了。非常感谢解释。 :) – dafrito 2013-04-08 20:24:20