std::any 和auto应用对比

一、std::any

这个在前面总结过,它是一个类型容器。可以动态的存储各种类型。说得牵强一些,有点类似于早期的void*,理论上可以转成各种类型的指针。它的实现就用到了前面分析过的std::decay_t。它是从C++17才出现的。
既然它可以动态的转换类型,那么就会有一种场景应用到它,那就是动态扩展类的功能属性。举个例子,有一个汽车的类,原来只有红和黄两种颜色属性,如果后期想增加的话,怎么办?根据设计原则的开闭原则,直接增加是非常坏的一种代码形式。
那么有人提出可以用容器来处理,比如std::map,很好,但是容器的类型要求是固定的,可是如果增加了一个时间属性呢?可以用std::variant,但是std::variant需要提前定义好数据类型,不友好。那么还是么std::any 好。看下面的例子:

class Test
{
public:
  Test(){}
  ~Test(){}
private:
  std::map<std::string,std::any> m_;
}

这种场景有兴趣可以试试。

二、auto

auto发展的过程老长了,从最初的可以定义普通变量,到后来越来越强大,应用的也越来越广泛。从普通函数的参数到Lambda表达式的参数到模板返回值的推断,下面看它的一些应用场景:
1、普通的变量定义和结构化绑定
这个容易理解:

auto x = 100;

//c++14
auto z = 6 + 2;
decltype(auto) y = z; 

std::tuple<float&, char&&, int> tpl(x, std::move(y), z);
const auto& [a, b, c] = tpl;

2、返回值推导

//c++11
template<class T, class U>
auto add(T t, U u) -> decltype(t + u) // the return type of add is the type of operator+(T,U)
{
    return t + u;
}
//c++14
template<class T, class U>
auto add(T t, U u) { return t + u; } // 返回类型是 operator+(T, U) 的类型
 
// 在它调用的函数返回引用的情况下
// 函数调用的完美转发必须用 decltype(auto)  
template<class F, class... Args>
decltype(auto) PerfectForward(F fun, Args&&... args) 
{ 
    return fun(std::forward<Args>(args)...); 
}
//使用返回类型推导的函数或函数模板的重声明或特化必须使用同一返回类型占位符:
template<typename T>
auto g(T t) { return t; }
template auto g(int);     // OK:返回类型是 int
// template char g(char); // 错误:不是主模板 g 的特化

3、Lambda表达式中的应用

auto lambda1 = [](auto a, auto b) {return a + b;}; // 返回类型为decltype(a+b)

4、函数参数应用

void f1(auto a); // 等同于 template<class T> void f(T t)  

auto Test(auto a, auto b)
{
	return (a == b) ? (a) : (b);
}

auto v = Test(1, 3.0); 

5、非模板参数类型应用

template<auto n>   // C++17 中非模板类型参数
auto f() -> std::pair<decltype(n), decltype(n)> // auto无法推导初始化列表形式
{
    return {n, n};
}

基本的应用场景就是上面的几种了,还有一些细小的应用大家可以 在实际用到查一下文档即可。

三、二者的不同

从上面的二者的应用还真得有很大的不同,这也说明了二者真的区别很大,但是只要抓住下面的两点就全明白了:
1、内容形式不同
std::any是一个容器,类似于std::vector之类,可以使用各种数据类型。auto是一个关键字,可以 认为是一种类型说明符,类似于int,double之类的数据类型。
2、状态不同
std::any是一个在运行期应用的容器,它是动态的,可以随时改变的。 auto是在编译期确定的,只要确定后,就无法再更改了。这样理解更容易形象的建立二者的不同。

四、总结

在形式上的应用二者看似有些相同,但实际上却有着非常大的区别。偶然看到有人问这个问题,发现自己对其中一些细节发展其实也不是特别清楚,所以整理一下。在前面已经对二者进行过分析说明,所以这里就不再展开,只是把一些要点总结一下。

猜你喜欢

转载自blog.csdn.net/fpcc/article/details/131589082