为什么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
-限定。在const t&
(相当于t const&
)中,限定不是顶级的:事实上,它并不应用于引用本身(这将是没有意义的,因为引用根据定义是不可变的),而是应用于被引用的类型。
C++11标准第20.9.7.1段中的表52针对std::remove_const
:
成员typedef类型应命名与t
相同的类型,但删除了任何顶级const-qualifier。[示例:remove_const
计算结果为volatile int
,而remove_const
计算结果为const int*
。-结尾示例]
为了删除const
,您必须首先应用std::remove_reference
,然后应用std::remove_const
,然后(如果需要)应用std::add_lvalue_reference
(或适合您的任何情况)。
注意:正如Xeo在注释中提到的,您可以考虑使用一个别名模板(如inqualified
)来执行前两个步骤,即去掉引用,然后去掉const
-(和volatile-
)限定。