auto类型推导和打印

#include "gtest/gtest.h"

#include <iostream>
#include <type_traits>
#include <typeinfo>

#ifndef _MSC_VER
#include <cxxabi.h>
#endif

#include <memory>
#include <string>
#include <cstdlib>

using namespace std;

template <class T>
std::string type_name()
{
    typedef typename std::remove_reference<T>::type TR;
    std::unique_ptr<char, void(*)( void* )> own
    (
    #ifndef _MSC_VER
            abi::__cxa_demangle(typeid( TR ).name(), nullptr,
                nullptr, nullptr),
    #else
            nullptr,
    #endif
        std::free
    );
    std::string r = own != nullptr ? own.get() : typeid( TR ).name();
    if (std::is_const<TR>::value)
        r += " const";
    if (std::is_volatile<TR>::value)
        r += " volatile";
    if (std::is_lvalue_reference<T>::value)
        r += "&";
    else if (std::is_rvalue_reference<T>::value)
        r += "&&";
    return r;
}

#define TYPENAME(obj) string(#obj).append(": <").append(string(type_name<decltype(obj)>())).append(">")
#define DUMPTYPE(obj) cout << TYPENAME(obj) << endl;



class Foo {
private:
    int a{1};
    int *ptr = &a;
public:
    int& getRef() {return a;}
    const int& getConstRef() {return a;}
    int* getPtr() {return ptr;}
    const int* getConstPtr() {return ptr;}

    //-----------------------------------------------
    auto getR() -> int& {return a;}     // 和getRef一样,需要用auto&接收;
    // auto& getR1() -> int {return a;} // 不能这样写 —— error: ‘getR1’ function with trailing return type has ‘auto&’ as its type rather than plain ‘auto’
        // 【trailing return type,如果是引用,只能写在后面】
    auto getR2() -> decltype((a)) {return a;} // 注意
    auto getR3() -> decltype(std::ref(a)) {return a;} // 可以编过,但是会变成<std::reference_wrapper<int>>

    // auto getCR() -> int& const {return a;} // 不能这样写 —— error: ‘const’ qualifiers cannot be applied to ‘int&’
    const auto getCR() -> int& {return a;}
    const auto getCR1() -> decltype((a)) {return a;}

    // auto getP() -> int* {return ptr;}; // 也不能这样写 —— error: invalid conversion from ‘int*’ to ‘int’ [-fpermissive]
    // auto getP() -> decltype(int*) {return ptr;}; // 这样写也不行 —— error: invalid conversion from ‘int*’ to ‘int’ [-fpermissive]
    auto getP() -> decltype(ptr) {return ptr;}; // 只能这样写
    const auto getCP() -> decltype(ptr) {return ptr;}
    //-----------------------------------------------
};

void testFunc() {
    Foo foo;
    auto valueGetRef = foo.getRef();            DUMPTYPE(valueGetRef); // 丢失引用
    auto valueGetConstRef = foo.getConstRef();  DUMPTYPE(valueGetConstRef); // 丢失引用和const
    const auto cValueGetRef = foo.getRef();     DUMPTYPE(cValueGetRef);

    auto& refGetConstRef = foo.getConstRef();           DUMPTYPE(refGetConstRef);   // 丢失const
    const auto& cRefGetConstRef = foo.getConstRef();    DUMPTYPE(cRefGetConstRef);
    const auto& cRefGetRef = foo.getRef();              DUMPTYPE(cRefGetRef);   // 即使获取的不是const,用const auto&接收也会变成const
    auto&& universalRefGetConstRef = foo.getConstRef(); DUMPTYPE(universalRefGetConstRef);

    //-----------------------------------------------
    auto valueGetR = foo.getR();        DUMPTYPE(valueGetR);
    // auto valueGetR1 = foo.getR1();   DUMPTYPE(valueGetR1);
    auto valueGetR2 = foo.getR2();      DUMPTYPE(valueGetR2);
    auto valueGetR3 = foo.getR3();      DUMPTYPE(valueGetR3); // 不能这样使用:valueGetR3 = 2; 因为获得的不是引用

    auto& refGetR = foo.getR();         DUMPTYPE(refGetR);
    // auto& refGetR1 = foo.getR1();    DUMPTYPE(refGetR1);
    auto& refGetR2 = foo.getR2();       DUMPTYPE(refGetR2);
    const auto& cRefGetR2 = foo.getR2();    DUMPTYPE(cRefGetR2);

    auto valueGetCR = foo.getCR();      DUMPTYPE(valueGetCR);
    auto valueGetCR1 = foo.getCR1();    DUMPTYPE(valueGetCR1);  
    auto& refGetCR = foo.getCR();       DUMPTYPE(refGetCR);  
    auto& refGetCR1 = foo.getCR1();     DUMPTYPE(refGetCR1);
    const auto& cRefGetCR = foo.getCR1();     DUMPTYPE(cRefGetCR);
    const auto& cRefGetCR1 = foo.getCR1();    DUMPTYPE(cRefGetCR1);

    auto valueGetP = foo.getP();        DUMPTYPE(valueGetP);
    auto valueGetCP = foo.getCP();      DUMPTYPE(valueGetCP);
    // auto& refGetP = foo.getP();         DUMPTYPE(refGetP); // error: cannot bind non-const lvalue reference of type ‘int*&’ to an rvalue of type ‘int*’

    //-----------------------------------------------
}

void t1();

TEST(TestAuto, TestAuto)
{
    auto x = 27;            DUMPTYPE(x);
    auto &rx = x;           DUMPTYPE(rx);
    const auto cx = x;      DUMPTYPE(cx);
    const auto &crx = x;    DUMPTYPE(crx);
    auto px = &x;           DUMPTYPE(px);
    const auto cpx = &x;    DUMPTYPE(cpx);

    auto &&uref1 = x;   DUMPTYPE(uref1);
    auto &&uref2 = rx;  DUMPTYPE(uref2);
    auto &&uref3 = cx;  DUMPTYPE(uref3);
    auto &&uref4 = cx;  DUMPTYPE(uref4);
    auto &&uref5 = 27;  DUMPTYPE(uref5);

    const char name[] = "a b b";    DUMPTYPE(name);
    auto arr1 = name;               DUMPTYPE(arr1);
    auto &arr2 = name;              DUMPTYPE(arr2);

    auto x1 = 27;           DUMPTYPE(x1);
    auto x2(27);            DUMPTYPE(x2);
    auto x3 = {27};         DUMPTYPE(x3);
    auto x3_2 = {27,28};    DUMPTYPE(x3_2);
    auto x4{27};            DUMPTYPE(x4);
//    auto x5{27,38}; //error
/*
main.cpp:67:15: error: direct-list-initialization of ‘auto’ requires exactly one element [-fpermissive]
  auto x5{27,38}; //error
               ^
main.cpp:67:15: note: for deduction to ‘std::initializer_list’, use copy-list-initialization (i.e. add ‘=’ before the ‘{’)
*/

    testFunc();
    t1();
}
posted @ 2021-12-05 22:50  zuksan  阅读(202)  评论(0)    收藏  举报