2012-10-07 61 views
1

看来,要测试常量,必须测试模板参数,但要测试右值,必须测试实际参数。 (这是使用VC++ 2012.)这段代码说明了我的意思:澄清通缉。 C++ type_traits

#include <type_traits> 
#include <string> 
#include <iostream> 

using namespace std; 

template<class T> 
void f(T& x) { 
    cout << "f() is_const<T> and is_const<decltype<x)>" << endl; 
    cout << is_const<T>::value << endl; // Prints 1 when arg is const 
    cout << is_const<decltype(x)>::value << endl; // Prints 0 when arg is const 
} 

template<class T> 
void g(T&& x) { 
    cout << "g() is_const<T> and is_const<decltype<x)>" << endl; 
    cout << is_const<T>::value << endl; // Prints 0 when arg is const 
    cout << is_const<decltype(x)>::value << endl; // Prints 0 when arg is cons 
    cout << "g() is_rvalue_reference<T> and is_rvalue_reverence<decltype(x)>" <<endl; 
    cout << is_rvalue_reference<T>::value << endl; // Prints 0 when arg is rvlaue 
    cout << is_rvalue_reference<decltype(x)>::value << endl; // Prints 1 when arg is rvalue 
} 

int main() 
{ 
    const std::string str; 
    f(str); // const argument 
    cout << endl; 
    g(std::string("")); // rvalue argument 
    return 0; 
} 

我很努力地理解这是为什么。有人可以解释,或者指给我一篇解释它的文章吗?如果需要,我将深入研究C++ 11标准。任何人都知道有关的部分?

+2

'const'是*型*的一部分。 “Rvalue”是一个值类别,它是*表达式*的一部分。两件不同的事情。 –

回答

5

原因是你误解了事情。 x在任何这些示例中都不会是const,只是因为没有const引用类型(无论如何您都无法更改引用)。在is_const<T>你基本上忽略了你宣称xT&

一个类似的误解正在为rvalue ref测试工作。 T&&(称为通用参考,btw)将在通过左值时推导为U&,当您传递右值时推导为U。在测试is_rvalue_reference<T>时,您再次忽略了您宣称xT&&。在测试is_const<T>时,您没有考虑到T将作为参考,如上所述,该参数永远不可能为const

g正确的测试将是

  • std::is_const<typename std::remove_reference<T>::type>::value
  • std::is_rvalue_reference<T&&>::value
+0

谢谢。我不好意思不好意思,或者这个问题可能已经做到了。我猜想,让我困惑的一件事是,is_const ::值从不是真实的参考,尽管所有参考的性质是不变的。这是指针和参考之间的主要区别。 Const指针必须这样声明。我试着声明一个引用为const。 VC++ 2012告诉我这是一个“时代错误”。在VC++ 2012头文件中,有一个is_const 来自false_type的专门化。所以一个参考is_const永远不会,尽管它始终是不变的。 –

+0

@Jive:让你听起来像你认为标准是有道理的。 :) – Xeo

+0

我在80年代后期就放弃了。我甚至质疑添加参考文献的智慧。 const指针有什么问题?当然,这是在模板之前。用指针,语法清楚地表明你正在处理一个参考(按照常识来说)。与“参考”不同。“顺便说一句,我认为VC++使用了与“不合时代”不同的词。 “过时的”我认为是。 –