const临时从模板类型和为什么使用std :: add_const? [英] Const temporary from template type and why use std::add_const?
问题描述
以下代码摘自 cppreference.com 。
#include< iostream>
这里应该是
#include< type_traits>
struct foo
{
void m(){std :: cout< non-cv \\\
; }
void m()const {std :: cout<< Const\\; }
};
template< class T>
void call_m()
{
T()。m();
}
int main()
{
call_m< foo>();
call_m< std :: add_const< foo> :: type>();但是,当使用VC ++ 2012年11月CTP编译时,输出为
非cv
非cv
< blockquote>
而不是预期:
非cv
Const
此外,以下两个语句之间有什么区别:
call_m< const foo>();
和
call_m< std :: add_const< foo> :: type>();
解决方案这似乎是MSVC的一个错误。使用形式
T()
的表达式(这是一个显式类型转换,就标准而言)导致指定类型的prvalue。
表达式
T()
,其中T
是非数组完整对象类型或(可能是cv限定的)的 simple-type-specifier 或 typename-specifier void
type,创建指定类型的prvalue,它是值初始化的
非类类型,由于非类prvalues不能具有cv限定类型的规则,
const
将被忽略:
类prvalues可以有cv限定类型;因此,由
T()创建的临时对象
const
,因此应该调用const
成员函数。
至于何时和为什么你会使用
std :: add_const
,我们可以看看它包含在提案。它说明add_const
,add_volatile
,add_cv
code> add_pointer 和add_reference
type traits已从提案中移除,但在Boost用户的投诉后恢复。
基本原理是这些模板都用作编译时函数,将一种类型转换为另一种类型[...]
给出的示例是:
// transforms'tuple< T1,T2,...,Tn>'
//到'tuple< T1 const&,T2 const&,..,Tn const& typename Tuple>
struct tuple_of_refs
{
// transform tuple element types
typedef typename mpl :: transform<
typename Tuple :: elements,
add_reference< add_const< _1> > // 这里!
> :: type refs;
typedef typename tuple_from_sequence< refs> :: type type;
};
template< typename Tuple>
typename tuple_of_refs< Tuple> :: type
tuple_ref(Tuple const& t)
{
return typename tuple_of_refs< Tuple> :: type(t);
}
你可以想到
mpl :: transform
作为其编译时元编程相当于作为其第二模板参数的函数指针 -
add_reference< add_const< ...>>
Tuple :: elements
中的每个类型。这根本不能用const
表示。The following code is excerpted from cppreference.com.
#include <iostream> #include <type_traits> struct foo { void m() { std::cout << "Non-cv\n"; } void m() const { std::cout << "Const\n"; } }; template <class T> void call_m() { T().m(); } int main() { call_m<foo>(); call_m<std::add_const<foo>::type>(); }
However, when compiled with VC++ Nov 2012 CTP, the output is
Non-cv
Non-cv
rather than the expected:
Non-cv
Const
Besides, what's the difference between the following two statements:
call_m<const foo>();
and
call_m<std::add_const<foo>::type>();
解决方案This appears to be a bug with MSVC. Using an expression of the form
T()
(which is an explicit type conversion, as far as the standard is concerned) results in a prvalue of the specified type.The expression
T()
, whereT
is a simple-type-specifier or typename-specifier for a non-array complete object type or the (possibly cv-qualified)void
type, creates a prvalue of the specified type, which is value-initializedIt is only with non-class types that the
const
would be ignored, due to a rule that non-class prvalues cannot have cv-qualified types:Class prvalues can have cv-qualified types; non-class prvalues always have cv-unqualified types.
So the temporary object created by
T()
here should beconst
and should therefore call theconst
member function.As for when and why you would use
std::add_const
, we can take a look at the reason it was included in the proposal. It states that theadd_const
,add_volatile
,add_cv
,add_pointer
, andadd_reference
type traits were removed from the proposal but then reinstated after complaints from users of Boost.The rationale is that these templates are all used as compile time functors which transform one type to another [...]
The example given is:
// transforms 'tuple<T1,T2,..,Tn>' // to 'tuple<T1 const&,T2 const&,..,Tn const&>' template< typename Tuple > struct tuple_of_refs { // transform tuple element types typedef typename mpl::transform< typename Tuple::elements, add_reference< add_const<_1> > // here! >::type refs; typedef typename tuple_from_sequence<refs>::type type; }; template< typename Tuple > typename tuple_of_refs<Tuple>::type tuple_ref(Tuple const& t) { return typename tuple_of_refs<Tuple>::type(t); }
You can think of
mpl::transform
as taking the compile-time metaprogramming equivalent to a function pointer as its second template argument -add_reference<add_const<...>>
is applied to each of the types inTuple::elements
. This simply couldn't be expressed usingconst
.这篇关于const临时从模板类型和为什么使用std :: add_const?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!