带有常量引用的 std::remove_const
为什么 std::remove_const
不将 const T&
转换为 T&
?这个公认的相当人为的例子证明了我的问题:
Why does std::remove_const
not convert const T&
to T&
? This admittedly rather contrived example demonstrates my question:
#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;
}
上述情况很容易解决,因此对于上下文,请想象以下内容:
The above case is trivially easy to fix, so for context, imagine the following:
#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
.
In the above example, I'd expect reference
to be shown, rather than constref
.
推荐答案
std::remove_const
移除了顶级 const
-qualifications.在 const T&
中,等同于 T const&
,限定不是顶级的:实际上,它不适用于引用本身(即没有意义,因为根据定义,引用是不可变的),而是针对被引用的类型.
std::remove_const
removes top level const
-qualifications. In const T&
, which is equivalent to T const&
, the qualification is not top-level: in fact, it does not apply to the reference itself (that would be meaningless, because references are immutable by definition), but to the referenced type.
C++11 标准第 20.9.7.1 段表 52 规定,关于 std::remove_const
:
Table 52 in Paragraph 20.9.7.1 of the C++11 Standard specifies, regarding std::remove_const
:
成员 typedef 类型应命名为与 T
相同的类型,除了任何顶级常量限定符已被删除.[ 示例:remove_const
计算结果为volatile int
,而 remove_const
计算const int*
.― 结束示例 ]
The member typedef type shall name the same type as
T
except that any top-level const-qualifier has been removed. [ Example:remove_const<const volatile int>::type
evaluates tovolatile int
, whereasremove_const<const int*>::type
evaluates toconst int*
. ― end example ]
为了去掉const
,你首先要应用std::remove_reference
,然后应用std::remove_const
,然后(如果需要)应用 std::add_lvalue_reference
(或任何适合您的情况).
In order to strip const
away, you first have to apply std::remove_reference
, then apply std::remove_const
, and then (if desired) apply std::add_lvalue_reference
(or whatever is appropriate in your case).
注意:正如 Xeo 在评论中提到的,您可以考虑 使用别名模板,例如 Unqualified
执行前两步,即去掉引用,然后去掉const
-(和volatile-
)限定.
NOTE: As Xeo mentions in the comment, you may consider using an alias template such as Unqualified
to perform the first two steps, i.e. strip away the reference, then strip away the const
- (and volatile-
) qualification.
相关文章