Boost - 数据类型

  • auto

  • decltype

  • any

  • tuple

  • variant

auto:

auto是C++11中的关键字,它可以通过类型推导自动得到变量或对象的类型,需要注意的是auto会忽略引用,因为引用其实就代表原对象:

用法1:

auto x = 1;

用法2:

for(auto &x : arr)

decltype:

如果我们希望从表达式中推断出要定义变量的类型,但却不想用表达式的值去初始化变量,那么可以使用decltype,需要注意的是如果decltype使用的变量加上一个括号的话那么decltype会返回对应的引用类型:

用法:

    int func(int i)
    {
        return i;
    }
    decltype(func(0)) num = 100; //num是int类型,不会调用func()

    int i = 100;
    decltype((i)) d = num; //d是int引用类型,其指向num

any:

any功能与auto类似,二者不同之处在于:

  1. auto是一个类似int、double、string的C++关键字,它不是一个类,所以没有成员函数可调用,直接把他当做int、double、string这种关键字来使用。

  2. any是一个类,只能通过any_cast<>获得any的实际内部值,而不能像auto定义的对象那样直接使用它。

  3. any也可以用来存储任意类型元素,如int、double、string、vector或自定义类型。它能够存储任意类型的原因是其构造函数和赋值函数opeartor=是模板函数,可以接收任意类型。

  4. any不是一个模板类,所以定义元素的时候不必使用<>,如any a = 10;

需要注意的有两点:

  1. 在any存储字符串的时候只能使用string,如any a = string(“hello”);,不能使用C风格的字符串,如:any a = “hello”;
  2. 如果保存动态内存指针类型,会引起内存泄露,解决方法是使用智能指针shared_ptr来指向动态内存,如:shared_ptr ptrSmart(new char[10]); any a = ptrSmart;

any的出现让C++仿佛变成了一种弱类型的动态语言。

使用:

  • any::empty()判断any是否为空
  • any::type()获得内部对象的类型,是一个标准type_info类的引用
  • any_cast<>()获得any内部对象值或内部对象指针或内部对象的引用

用法:

#include <vector>
#include "boost/any.hpp"
#include "boost/assign.hpp"
using namespace boost::assign;


template <typename T> 
bool match_type(boost::any& a)
{
    if (a.empty())
        return false;

    return typeid(T) == a.type();
}

template<typename T> 
T get_value(boost::any& a)
{
    BOOST_ASSERT(match_type<T>(a));

    return boost::any_cast<T>(a);
}

template <typename T> 
T* get_pointer(boost::any& a)
{
    BOOST_ASSERT(match_type<T>(a));

    return boost::any_cast<T>(&a);
}

template <typename T> 
T& get_reference(boost::any& a)
{
    BOOST_ASSERT(match_type<T>(a));

    return boost::any_cast<T&>(a);
}

int main()
{
    boost::any a = 10;

    int iNum = get_value<int>(a);//获得a的内部元素
    cout << iNum << endl;

    int * p = get_pointer<int>(a);//获得a内部元素的指针
    cout << *p << endl;

    get_reference<int>(a) = 5;//获得a内部元素引用,引用可以被当做左值来使用
    cout << *p << endl;

    if (match_type<int>(a))//判断a内部元素类型是否为int
        cout << "true" << endl;

    return 0;
}

tuple:

tuple类型类似于std::pair,pair只支持包含两种类型的元素,tuple可以支持包含多个不同类型的元素,比如将其用于多个返回值的函数的话比使用struct更方便.

用法:

#include <cstdio>
#include <string>
using std::string;
#include "boost/tuple/tuple.hpp"

int main()
{
    int i = 1;
    double d = 5.0;
    string s("hello");
    //tuple<int,double,string>
	auto tupleCombin = make_tuple(i,d,s);
    
    //tuple<const int&,double&,string>
    auto tupleCombin_2 = make_tuple(cref(i),ref(d),s); 
    
    BOOST_ASSERT(tupleCombin.get<0>() == 1);
    BOOST_ASSERT(tupleCombin.get<1>() == 5.0);
  
    return getchar();
}

variant:

variant是一种增强的union,C/C++中union只能持有POD(普通数据类型),而不能持有如string、vector等复杂类型,boost的variant则没有这个限制。

用法:

#include<boost/variant.hpp>

int main()
{
    variant<int,float,string> v;
    v = "123";
    cout <<v <<endl;
    
    try
    {
        cout << get<float>(v)<<endl;
    }
    catch(boost::bad_get&)
    {
        cout <<"bad_get"<<endl;
	}
    
    if(v.type() == typeid(int))
    {
        cout << get<int>(v) <<endl;
    }
    else  if(v.type() == typeid(double))
    {
        cout << get<double>(v) <<endl;
    }

}