9_3_boost_类型推断.cpp
#include "hjcommon.hpp"
#include "boost/type_index.hpp"
template<typename T, typename Q>
static void aFunc(T &tvar, const Q &qvar) // 把引用换乘指针,行为是一样的
{
using boost::typeindex::type_id_with_cvr; // 使用 type_id_with_cvr ,可以得到数据类型或变量的数据类型名称
std::string TName = ((boost::typeindex::type_index)type_id_with_cvr<T>()).pretty_name();
std::string QName = ((boost::typeindex::type_index)type_id_with_cvr<Q>()).pretty_name();
std::string tvarName = ((boost::typeindex::type_index)type_id_with_cvr<decltype(tvar)>()).pretty_name();
std::string qvarName = ((boost::typeindex::type_index)type_id_with_cvr<decltype(qvar)>()).pretty_name();
cout << "T=" << TName << ", tvar=" << tvarName << ", Q=" << QName << ", qvar=" << qvarName << endl;
}
template<typename T>
static void bFunc(T &tvar1, const T &tvar2) // 这种情况,当形参既有 T& 又有 const T&, T只会被推断为 int ,所以若实参为 const 类型时,编译器会报错
{
using boost::typeindex::type_id_with_cvr; // 使用 type_id_with_cvr ,可以得到数据类型或变量的数据类型名称
std::string TName = ((boost::typeindex::type_index)type_id_with_cvr<T>()).pretty_name();
std::string tvar1Name = ((boost::typeindex::type_index)type_id_with_cvr<decltype(tvar1)>()).pretty_name();
std::string tvar2Name = ((boost::typeindex::type_index)type_id_with_cvr<decltype(tvar2)>()).pretty_name();
cout << "T=" << TName << ", tvar1=" << tvar1Name << ", tvar2=" << tvar2Name << endl;
}
template<typename T>
static void cFunc(T &&tvar) // 万能引用
{
using boost::typeindex::type_id_with_cvr; // 使用 type_id_with_cvr ,可以得到数据类型或变量的数据类型名称
std::string TName = ((boost::typeindex::type_index)type_id_with_cvr<T>()).pretty_name();
std::string tvarName = ((boost::typeindex::type_index)type_id_with_cvr<decltype(tvar)>()).pretty_name();
cout << "T=" << TName << ", tvar=" << tvarName << endl;
}
template<typename T>
static void dFunc(T tvar) // 传值方式
{
using boost::typeindex::type_id_with_cvr; // 使用 type_id_with_cvr ,可以得到数据类型或变量的数据类型名称
std::string TName = ((boost::typeindex::type_index)type_id_with_cvr<T>()).pretty_name();
std::string tvarName = ((boost::typeindex::type_index)type_id_with_cvr<decltype(tvar)>()).pretty_name();
cout << "T=" << TName << ", tvar=" << tvarName << endl;
}
template<typename T>
static void eFunc(T &tvar) // 数组
{
using boost::typeindex::type_id_with_cvr; // 使用 type_id_with_cvr ,可以得到数据类型或变量的数据类型名称
std::string TName = ((boost::typeindex::type_index)type_id_with_cvr<T>()).pretty_name();
std::string tvarName = ((boost::typeindex::type_index)type_id_with_cvr<decltype(tvar)>()).pretty_name();
cout << "T=" << TName << ", tvar=" << tvarName << endl;
}
template<typename T, unsigned len>
static void eeFunc(T (&tvar)[len]) // 数组
{
using boost::typeindex::type_id_with_cvr; // 使用 type_id_with_cvr ,可以得到数据类型或变量的数据类型名称
std::string TName = ((boost::typeindex::type_index)type_id_with_cvr<T>()).pretty_name();
std::string tvarName = ((boost::typeindex::type_index)type_id_with_cvr<decltype(tvar)>()).pretty_name();
cout << "T=" << TName << ", tvar=" << tvarName << ", len=" << len << endl;
}
static void test() {}
template<typename T>
static void fFunc(T tvar) // 函数名作实参
{
using boost::typeindex::type_id_with_cvr; // 使用 type_id_with_cvr ,可以得到数据类型或变量的数据类型名称
std::string TName = ((boost::typeindex::type_index)type_id_with_cvr<T>()).pretty_name();
std::string tvarName = ((boost::typeindex::type_index)type_id_with_cvr<decltype(tvar)>()).pretty_name();
cout << "T=" << TName << ", tvar=" << tvarName << endl;
}
template<typename T>
static void gFunc(T &tvar) // 函数名作实参
{
using boost::typeindex::type_id_with_cvr; // 使用 type_id_with_cvr ,可以得到数据类型或变量的数据类型名称
std::string TName = ((boost::typeindex::type_index)type_id_with_cvr<T>()).pretty_name();
std::string tvarName = ((boost::typeindex::type_index)type_id_with_cvr<decltype(tvar)>()).pretty_name();
cout << "T=" << TName << ", tvar=" << tvarName << endl;
}
int main_2_9_3(int argc, char *argv[])
{
// boost库:开源,比较悠久
// boost库下载:https://www.boost.org 解压目录:/usr/local/cpp/boost_1_69_0
// cd /usr/local/cpp/boost_1_69_0
// sudo ./bootstrap.sh --prefix=/usr/local/cpp/boost
// sudo ./b2 install // 编译需要很久.
// 最后会在 /usr/local/cpp/boost/ 下生成 include 与 lib 目录
// 将 /usr/local/cpp/boost/include 添加进eclipse环境变量, 记得还要在 CMakeList.txt 中include该路径,否则编译时会找不到, 链接不需要指定so库?
// eclipse的环境变量有点问题。。 我直接将 /usr/local/cpp/boost/include/boost 头文件目录复制到了 /usr/local/include 下了。
int a = 0; long aa = 0;
const int b = a; const long bb = aa;
const int &c = 1; const long &cc = 1;
int &&d = 1; long &&dd = 1;
const int &&e = 1; const long &&ee = 1;
cout << "------------------引用与指针---------------------" << endl;
aFunc(a, aa); // T=int, tvar=int&, Q=long, qvar=long const&
aFunc(b, bb); // T=int const, tvar=int const&, Q=long, qvar=long const&
aFunc(c, cc); // T=int const, tvar=int const&, Q=long, qvar=long const&
aFunc(d, dd); // T=int, tvar=int&, Q=long, qvar=long const&
aFunc(e, ee); // T=int const, tvar=int const&, Q=long, qvar=long const&
cout << "-------------------T& 且 const T&--------------------" << endl;
bFunc(a, a); // 可以
// bFunc(b, b); // 这种情况,当形参既有 T& 又有 const T&, T只会被推断为 int ,所以若给实参 T& 传 const 类型时,编译器会报错
// bFunc(c, c); // 不可以
bFunc(d, d); // 可以
// bFunc(e, e); // 不可以
cout << "------------------万能引用---------------------" << endl;
cFunc(a); // T=int&, tvar=int&
cFunc(b); // T=int const&, tvar=int const&
cFunc(c); // T=int const&, tvar=int const&
cFunc(d); // T=int&, tvar=int&
cFunc(e); // T=int const&, tvar=int const& // 虽然 d与e 是右值,但是当使用 d与e 时,却是被当作左值来使用的。
cFunc(7); // T=int, tvar=int&&
cout << "------------------传值方式 T t ---------------------" << endl;
dFunc(a); // T=int, tvar=int
dFunc(b); // T=int, tvar=int // const 属性没有传递进去,也就是函数模板中,参数可以修改
dFunc(c); // T=int, tvar=int
dFunc(d); // T=int, tvar=int
dFunc(e); // T=int, tvar=int
char f[] = "some";
const char *g = f;
const char *const h = g;
const char i[] = "hi";
dFunc(f); // T=char *, tvar=char *
dFunc(g); // T=char const*, tvar=char const* // 当实参为常指针时,const属性能传递进去一部分
dFunc(h); // T=char const*, tvar=char const*
dFunc(i); // T=char const*, tvar=char const*
cout << "------------------数组---------------------" << endl;
eFunc(i); // T=char const [3], tvar=char const (&) [3]
eeFunc(i); // T=char const, tvar=char const (&) [3], len=3 // 数组引用
cout << "------------------函数名作实参---------------------" << endl;
fFunc(test); // T=void (*)(), tvar=void (*)() // 函数指针
gFunc(test); // T=void (), tvar=void (&)() // 函数类型引用
return 0;
}
9_5_auto.cpp
#include "hjcommon.hpp"
#include "boost/type_index.hpp"
template<typename T>
static void aFunc(T &tvar)
{
using boost::typeindex::type_id_with_cvr; // 使用 type_id_with_cvr ,可以得到数据类型或变量的数据类型名称
std::string TName = ((boost::typeindex::type_index)type_id_with_cvr<T>()).pretty_name();
std::string tvarName = ((boost::typeindex::type_index)type_id_with_cvr<decltype(tvar)>()).pretty_name();
cout << "T=" << TName << ", tvar=" << tvarName << endl;
}
static auto abc() { return 0; } // c++14,auto可作为函数返回值类型
class A
{
public:
static const auto m_num = 0; // auto可作为静态成员变量,且必须是const,可以而且必须在类内初始化。。
};
int main_2_9_5()
{
// auto : auto有类型,auto的变量也有类型,类似于模板类型参数 T
auto a = 1; // 可以,int
const auto b = 1; // 可以,const int
const auto &c = a; // 可以,const int&
const auto &d = 1; // 可以,const int&
auto &&e = 1; // 可以,int&&
// const auto &&f = a; // 不可以,const右值引用,不能用左值赋
const auto &&g = 1; // 可以,cosnt int&&
auto &h = c; // cosnt int& ,auto会丢弃引用属性(引用折叠了),但不会丢弃const属性
auto hh = b; // int,同模板参数传值方式一样
auto i { 30 }; // int
auto j = { 30 }; // std::initializer_list<int> c++11新数据类型,类模板,表示特定值的数组
std::string tName = ((boost::typeindex::type_index)boost::typeindex::type_id_with_cvr<decltype(j)>()).pretty_name();
cout << "tName=" << tName << endl;
// auto 不能作为函数形参、不能作为非静态成员变量
return 0;
}
9_6_decltype.cpp
#include "hjcommon.hpp"
#include "boost/type_index.hpp"
class A
{
public:
int i;
};
static int func()
{
cout << "func." << endl;
return 0;
}
int main_2_9_6()
{
// decltype() c++11,返回操作数的数据类型,同auto一样,编译期间推断。 decltype能保留引用符 & ,decltype类型推导几乎是原封不动的推导出操作数的数据类型
// decltype 操作数是变量 decltype() 可以声明变量。。
const int a = 0;
const int &b = a;
decltype(a) c = a; // c = const int
decltype(b) d = a; // d = const int &
decltype(A::i) e; // int
A aa;
decltype(aa.i) f; // int
auto &&g = a; // int &
decltype(g) &&h = a; // int & ,引用折叠了
// decltype 操作数是被表达式
decltype(2) i = 0; // int
int j = 0;
int *pj = &j;
decltype(*pj) k = i; // int &
decltype(j) l = j; // int
decltype( (j) ) m = j; // int & 。。
int mm = 0;
decltype(std::move(mm)) dm = 1; // int&& ,按道理 std::move(mm) 也不会真执行。
// decltype 操作数是函数
decltype(func()) n = 0; // int ,并不会调用func()函数。 同理 A() 也不会生成 A() 临时对象
decltype(func) *o = func; // int (void)
o();
// decltype 抽取操作数变量类型
vector<int> vec;
decltype(vec)::size_type size = vec.size();
// decltype 用于后置返回函数
// decltype(auto) c++14 ,可用于前置返回函数,推导 auto 的数据类型
const int &p = 0;
decltype(auto) r = p; // const int &
std::string tName = ((boost::typeindex::type_index)boost::typeindex::type_id_with_cvr<decltype(dm)>()).pretty_name();
cout << "tName=" << tName << endl;
return 0;
}