C++ 可以使用std::any_cast有效地强制转换std::any
我正在尝试使用我的库中的C++ 可以使用std::any_cast有效地强制转换std::any,c++,templates,casting,c++17,std,C++,Templates,Casting,C++17,Std,我正在尝试使用我的库中的std::any。我以cppreference.com为例,通过以下方式实现该示例: #include <any> #include <iostream> int main() { struct example_1{ int i1; int i2; }; // any type std::any a = 1; std::cout << a.type().nam
std::any
。我以cppreference.com为例,通过以下方式实现该示例:
#include <any>
#include <iostream>
int main()
{
struct example_1{
int i1;
int i2;
};
// 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';
struct example_1 ex1;
ex1.i1 = 1;
ex1.i2 = 2;
a = ex1;
std::cout << a.type().name() << ": " << std::any_cast<struct example_1>(a).i1 << " ; " << std::any_cast<struct example_1>(a).i2 << '\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 = 1;
if (a.has_value())
{
std::cout << a.type().name() << '\n';
}
// reset
a.reset();
if (!a.has_value())
{
std::cout << "no value\n";
}
// pointer to contained data
a = 1;
int* i = std::any_cast<int>(&a);
std::cout << *i << "\n";
}
在基本类型的情况下很容易,但在结构的情况下,我们将作为调用的返回std::any.type().name()
结构的符号
我认为要将传递的std::any
参数转换为正确的类型,如果包含子字符串“structname”或“classname”,我可以在符号字符串中搜索。但我认为这只是一个解决办法。有没有办法有效地将std::any
转换为正确的类型
另一个问题是,如果我在我的库中使用它,我不知道传递的对象的结构或类的名称(因此我的变通方法无法工作)。有没有办法检索它并使用正确类型的
std::any_cast
这是因为将在编译期间进行优化。如果要在运行时
上获取类型的全名,则必须demangle
类型的名称(这不是标准名称)
假设您的类型名位于字符串变量type\u name
中:
int demangle_status;
char* demangled_name = abi::__cxa_demangle(type_name.c_str(), nullptr, nullptr, &demangle_status;
if (demangle_status == 0)
{
type_name = demangled_name;
std::free(demangled_name)
}
std::cout << type_name
int-demangle\u状态;
char*demangled\u name=abi::\uuuucxa\u demangle(键入\u name.c\u str(),nullptr,nullptr,&demangle\u status;
如果(demangle_状态==0)
{
类型\名称=需求\名称;
标准::免费(demangled_名称)
}
std::cout这是因为编译过程中会进行优化。如果要在运行时
上获取类型的全名,必须demangle
类型的名称(这不是标准)
假设您的类型名位于字符串变量type\u name
中:
int demangle_status;
char* demangled_name = abi::__cxa_demangle(type_name.c_str(), nullptr, nullptr, &demangle_status;
if (demangle_status == 0)
{
type_name = demangled_name;
std::free(demangled_name)
}
std::cout << type_name
int-demangle\u状态;
char*demangled\u name=abi::\uuuucxa\u demangle(键入\u name.c\u str(),nullptr,nullptr,&demangle\u status;
如果(demangle_状态==0)
{
类型\名称=需求\名称;
标准::免费(demangled_名称)
}
std::cout由.type().name()
返回的值是完全由实现定义的,您对它们没有任何保证。您甚至不能保证.type().name()
对于多个不同的类型是不同的
即使不是这样,.type().name()
返回运行时值,并且不能使用非常量值来计算类型
C++是静态类型的。每个表达式(在模板实例化之后)在编译时都有一个固定的类型。因此,如果不知道它(可能)包含的类型,就不能使用std::any
您可以使用any\u cast
或.type()
返回的std::type\u info
获取std::any
持有的类型和值(通过它在.name()
之外提供的其他成员),仅当在编译时确定它可以在该代码位置(模板实例化后)保留有限的可能类型集时。如果不知道它在代码中给定位置(模板实例化后)保留的潜在类型,则无法获取它在该位置保留的类型或值
如果库的用户要将其类型与std::any
一起使用,并且您确实想要提取库代码中的值,那么您需要对代码进行模板化,并且用户需要将潜在类型作为模板参数提供给它
很少有情况下使用std::any
是有意义的。通常std::variant
或虚拟基类接口(用户可以从中派生自己的类型)更可能是合适的工具。或者,如果实际不需要运行时多态性(我们不知道您的用例),只需编写用户可以向其提供自定义类型的模板代码就足够了
也请注意:在C++的类型名称外定义类定义或显式前向声明之前不要使用 Stult<代码>。它不需要,但如果类型查找失败,则会有意想不到的后果。
< P>由代码> > Type().NAME()返回的值。
是完全由实现定义的,您对它们没有任何保证。您甚至不能保证.type().name()
对于多个不同的类型是不同的
即使不是这样,.type().name()
返回运行时值,并且不能使用非常量值来计算类型
C++是静态类型的。每个表达式(在模板实例化之后)在编译时都有一个固定的类型。因此,如果不知道它(可能)包含的类型,就不能使用std::any
您可以使用any\u cast
或.type()
返回的std::type\u info
获取std::any
持有的类型和值(通过它在.name()
之外提供的其他成员),仅当在编译时确定它可以在该代码位置(模板实例化后)保留有限的可能类型集时。如果不知道它在代码中给定位置(模板实例化后)保留的潜在类型,则无法获取它在该位置保留的类型或值
如果库的用户要将其类型与std::any
一起使用,并且您确实想要提取库代码中的值,那么您需要对代码进行模板化,并且用户需要将潜在类型作为模板参数提供给它
很少有情况下使用std::any
是有意义的。通常std::variant
或虚拟基类接口(用户可以从中派生自己的类型)更可能是合适的工具。或者,如果实际不需要运行时多态性(我们不知道您的用例),只需编写用户可以向其提供自定义类型的模板代码就足够了
<