#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();
}