std::any(C++17)
有点像python等脚本语言的动态类型,可以用于对C语言里void*类型的替换使用,相比void*类型安全,对于异常转换,可以通过try/catch进行捕获处理。
示例:
#include <any>
#include <iostream>
int main()
{
std::cout << std::boolalpha;
// any type
std::any a = 1;
std::cout << a.type().name() << ": " << std::any_cast<int>(a) << '\n';
a = 3.14;
std::cout << a.type().name() << ": " << std::any_cast<double>(a) << '\n';
a = true;
std::cout << a.type().name() << ": " << std::any_cast<bool>(a) << '\n';
// bad cast
try
{
a = 1;
std::cout << std::any_cast<float>(a) << '\n';
}
catch (const std::bad_any_cast& e)
{
std::cout << e.what() << '\n';
}
// has value
a = 2;
if (a.has_value())
{
std::cout << a.type().name() << ": " << std::any_cast<int>(a) << '\n';
}
// reset
a.reset();
if (!a.has_value())
{
std::cout << "no value\n";
}
// pointer to contained data
a = 3;
int* i = std::any_cast<int>(&a);
std::cout << *i << "\n";
}
/* output
int: 1
double: 3.14
bool: true
bad any_cast
int: 2
no value
3
*/
参考资料:std::any - cppreference.com
https://devblogs.microsoft.com/cppblog/stdany-how-when-and-why
std::optional(C++17)
对函数返回结果做一层封装,常见用于给返回值增加是否出错标记;比如pair<string,bool>这种返回值,对于返回的string希望可以判断是否函数内部异常出错,如果返回空,是正常逻辑空,还是异常错误空,有时候调用方是需要做分类处理的。示例代码:
#include <iostream>
#include <optional>
using namespace std;
string getString1(int param)
{
if (0 == param) return "";
string str; // do logic
return str;
}
optional<string> getString2(int param)
{
if (0 == param) return {};
string str; // do logic
return str;
}
int main()
{
int param = 0;
string str1 = getString1(param);
if (str1.empty()) { cout << "get empty str" << endl; }
optional<string> opt_str2 = getString2(param);
if (!opt_str2) { cout << "get failed, error happen" << endl; }
return 0;
}
参考资料:https://zhuanlan.zhihu.com/p/64985296
std::variant(C++17)
C++11如果想要一个函数返回多个变量,可以返回std::pair或std::tuple,C++17提供了std::variant;可以理解为类型安全的union(union多个字段共用内存,这里不共用),可以通过该特性对上述optional的返回错误做明确赋值。
示例代码:
#include <iostream>
#include <optional>
#include <variant>
using namespace std;
string getString1(int param)
{
if (0 == param)
return "";
string str; // do logic
return str;
}
optional<string> getString2(int param)
{
if (0 == param)
return {};
string str; // do logic
return str;
}
variant<string,int> getString3(int param)
{
if (0 == param) return -1;
string str; // do logic
return str;
}
int main()
{
int param = 0;
string str1 = getString1(param);
if (str1.empty()) { cout << "get empty str" << endl; }
optional<string> opt_str2 = getString2(param);
if (!opt_str2) { cout << "get failed, error happen" << endl; }
variant<string, int> var_str3 = getString3(param);
if (auto p = get_if<string>(&var_str3))
cout << "get normal str:" << *p << endl;
if (auto p = get_if<int>(&var_str3))
cout << "get failed error happen:" << *p << endl;
return 0;
}
/*
get empty str
get failed, error happen
get failed, error happen:-1
*/
protobuf::any(proto3)
在pb结构定义中,可以使用any类型,表示任意类型,使用时可以通过强制转化达到动态类型效果。
syntax = "proto3";
import "google/protobuf/any.proto";
message AnyType {
google.protobuf.Any data = 1;
}
代码示例:todo