It appears that to test for const-ness, one must test the template-parameter, but to test for rvalue-ness, one must test an actual parameter. (This is using VC++ 2012.) This code illustrates what I mean:
#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;
}
I am struggling to understand why that is. Can someone explain, or point me to an article that explains it? If need be, I will dig into the C++11 standard. Anyone know the pertinent sections?
The reason is that you’re misunderstanding things.
xwill never beconstin any of those examples, simply because there are noconstreference types (you can’t change what a reference refers to anyways). Inis_const<T>you’re basically ignoring that you declaredxasT&.A similar misunderstanding is at work for the rvalue ref test. The
TinT&&(which is called a universal reference, btw) will be deduced asU&when you pass an lvalue and asUwhen you pass an rvalue. When testingis_rvalue_reference<T>, you’re ignoring again that you declaredxasT&&. When testingis_const<T>, you didn’t account for the fact thatTwill be a reference, which, as said above, can never beconst.The correct tests for
gwould bestd::is_const<typename std::remove_reference<T>::type>::valueandstd::is_rvalue_reference<T&&>::value