C ++ template template argument output process

Can someone help me explain why the subtraction argument is not working as I expected? 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; } 
+4
source share
1 answer

I will take care of each of your comments.

  • deduce1 with d :

     template <class T> void deduce1(T args, string arg); int const d[] = {12}; deduce1(d, "int const d[] = {12}"); // would have thought is_const<T> would return true 

    The first important one is that you cannot pass arrays as arguments by value in C ++. Expressions denoting an array will almost immediately disappear with a pointer to its first element. So the type deduced for T will be int const * .

    So why this will not work? The problem is that the pointer is not const . int pointed to by the pointer is const . If you want to report the const value of the specified type, you will need to use remove_pointer before checking for const ness. So you would change the const check to:

     cout << "Is const: " << boolalpha << is_const<typename remove_pointer<T>::type>::value << endl; 

    However, the result he gave earlier was the correct answer. The pointer really was not const . In fact, even if the pointer was const , the top level of consts is removed before type inference is executed, so T will not be const anyway. The reason for this is that if you pass by value, you are really not interested in the const argument, since you are copying it anyway.

  • deduce2 with b :

     template <class T> void deduce2(T& args,string arg); const int b = 5; deduce2(b,"const int b = 5"); //would have though type would be deduced as int const 

    Not sure what is here for you, but my result is:

     deduced as: i Is const: true Is reference: false Is pointer: false 

    Just as expected.

  • deduce2 with c :

     int c[] = {12}; deduce2(c,"int c[] = {12}"); // why is this not returning true as a reference? 

    Saying that this is not a link for the same reason that all calls to deduce2 say that (and you have this problem all over deduce3 ). In your function, you check for type T , but type args is T& . You only check the part before & . So the type of args is int (&)[1] c , but you just check if int [1] reference. Correct it using decltype(args) instead of T in your checks.

  • deduce2 with d :

     int const d[] = {12}; deduce2(d,"int const d[] = {12}"); // would have thought is_const<T> would return true 

    Same problem as deduce1 with d (point 1).

  • deduce3 with c :

     template <class T> void deduce3(T&& args,string arg); int c[] = {12}; deduce3(c,"int c[] = {12}"); // why is this not returning true as a reference? 

    Same problem as deduce2 with c (point 3).

  • deduce3 with d :

     int const d[] = {12}; deduce3(d,"int const d[] = {12}"); // would have thought is_const<T> would return true 

    Same problem as deduce1 with d (point 1).

  • deduce3 using string("Hello") :

     deduce3(string("Hello"),"string(\"Hello\")"); // why not rvalue reference 

    I'm going to suggest that you know something about "universal links." Scott Meyers has an excellent article and talk on the subject.

    In this case, since string("Hello") is an rvalue expression, the type T is displayed as string (according to the rules of the derived reference types rvalue of the form T&& ). The args type is now string && . Therefore, if you check if decltype(args) is an rvalue value, it will say true. But T itself is not.

If you fix your code so that all type traits on T now decltype(args) , you will get a new problem. When args has a reference type, there will be no specific types that you expect to be const . This is because there is no such thing as a const reference. Similar to using remove_pointer in element 1, you need to use remove_reference to get the base type and check if it is const .

0
source

Source: https://habr.com/ru/post/1444529/


All Articles