const临时从模板类型和为什么使用std :: add_const? [英] Const temporary from template type and why use std::add_const?

查看:185
本文介绍了const临时从模板类型和为什么使用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(), where T 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-initialized

It 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 be const and should therefore call the const 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 the add_const, add_volatile, add_cv, add_pointer, and add_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 in Tuple::elements. This simply couldn't be expressed using const.

这篇关于const临时从模板类型和为什么使用std :: add_const?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆