Can anyone help tell me why the argument deduction is not working how I would anticipate? Please see my code comments for my line of thinking?
#include <iostream>
#include <type_traits>
#include <iomanip>
#include <string>
using namespace std;
template<class T>
void deduce1(T args, string arg){
cout << "template<class T> void deduce1(T args) " << " argument passed in was: " << arg << " deduced as: " << typeid(T).name() << endl;
cout << "Is const: " << boolalpha << is_const<T>::value << endl;
cout << "Is reference: " << boolalpha << is_reference<T>::value << endl;
cout << "Is pointer: " << boolalpha << is_pointer<T>::value << endl;
}
template<class T>
void deduce2(T& args,string arg){
cout << "template<class T> void deduce2(T args) " << " argument passed in was: " << arg << " deduced as: " << typeid(T).name() << endl;
cout << "Is const: " << boolalpha << is_const<T>::value << endl;
cout << "Is reference: " << boolalpha << is_reference<T>::value << endl;
cout << "Is pointer: " << boolalpha << is_pointer<T>::value << endl;
}
template<class T>
void deduce3(T&& args,string arg){
cout << "template<class T> void deduce3(T args) " << " argument passed in was: " << arg << " deduced as: " << typeid(T).name() << endl;
cout << "Is const: " << boolalpha << is_const<T>::value << endl;
cout << "Is reference: " << boolalpha << is_reference<T>::value << endl;
cout << "Is rvalue reference: " << boolalpha << is_rvalue_reference<T>::value << endl;
cout << "Is pointer: " << boolalpha << is_pointer<T>::value << endl;
}
int _tmain(int argc, _TCHAR* argv[])
{
int a = 1;
const int b = 5;
int c[] = {12};
int const d[] = {12};
int& e = a;
deduce1(a,"int a = 1");
deduce1(b,"const int b = 5");
deduce1(c,"int c[] = {12}");
deduce1(d,"int const d[] = {12}"); // would have thought is_const<T> would return true any comments?
deduce1(e,"int& e = a");
deduce1(5,"5");
deduce2(a,"int a = 1");
deduce2(b,"const int b = 5"); //would have though type would be deduced as int const comments?
deduce2(c,"int c[] = {12}"); // why is this not returning true as a reference?
deduce2(d,"int const d[] = {12}"); // would have thought is_const<T> would return true any comments
deduce2(e,"int& e = a");
deduce3(a,"int a = 1");
deduce3(b,"const int b = 5");
deduce3(c,"int c[] = {12}"); // why is this not returning true as a reference?
deduce3(d,"int const d[] = {12}"); // would have thought is_const<T> would return true any comments
deduce3(e,"int& e = a");
deduce3(string("Hello"),"string(\"Hello\")"); // why not rvalue reference
return 0;
}
I’ll tackle each of your comments in turn.
deduce1withd:The first important thing is that you can’t pass arrays as arguments by value in C++. Expressions denoting an array will decay almost immediately to a pointer to its first element. So the type deduced for
There will beint const *.So still, why won’t this work? The problem is that the pointer is not
const. Theints that the pointer is pointing to areconst. If you want to report theconstness of the type being pointed to, you’ll need to useremove_pointerbefore checking theconstness. So you would change yourconstchecking to:However, the result it was giving before was the correct answer. The pointer was indeed not
const. In fact, even if the pointer wereconst, top-levelconstsare stripped off before type deduction is done soTwould not beconstanyway. The reason for this is that, if you’re passing by value, you really don’t care about theconstness of the argument since you’re copying it anyway.deduce2withb:Not sure what’s happening for you here, but my output is:
Exactly as expected.
deduce2withc:It’s saying that it’s not a reference for the same reason all of the
deduce2calls say that (and you have this problem throughoutdeduce3too). In your function, you’re checking the type ofTbut the type ofargsisT&. You’re only checking the part before the&. So here, the type ofargsisint (&)[1] cbut you’re just checking ifint [1]is a reference. Fix it by usingdecltype(args)instead ofTin your checks.deduce2withd:Same problem as
deduce1withd(item 1).deduce3withc:Same problem as
deduce2withc(item 3).deduce3withd:Same problem as
deduce1withd(item 1).deduce3withstring("Hello"):I’m going to assume you know something about “universal references”. Scott Meyers has a great article and talk on the subject.
In this case, because
string("Hello")is an rvalue expression, the typeTis deduced asstring(by the rules of deduced rvalue reference types of the formT&&). The type ofargsis nowstring &&. So if you check ifdecltype(args)is an rvalue, it’ll say true. ButTitself is not.If you fix your code so that all type traits on
Tare now ondecltype(args), you’ll get a new problem. When args is of reference type, certain types that you expect to beconstwon’t be. That’s because there’s no such thing as aconstreference. Similar to usingremove_pointerin item 1, you’ll need to useremove_referenceto get at the underlying type and check if that isconst.