在C++中有没有一种方法可以将字符串与类型名称进行“比较”?

3

我有一个包含初始值的JSON和创建对象的管理器。这些值被读取为字符串,但管理器需要类型名称来创建对象。

我的代码大致如下:

for(auto obj_str : json["objs"])
{
    if(obj_str == "ObjectFoo")
    {
        manager.createObject<ObjectFoo>();
    }
    if(obj_str == "ObjectBar")
    {
        manager.createObject<ObjectBar>();
    }
    if(obj_str == "ObjectBaz")
    {
        manager.createObject<ObjectBaz>();
    }
}

有没有一种方式可以避免为每个对象使用if语句,并使用一个或多个通用函数? 对象的字符串始终与类型名称相同。

2
这个无法自动完成。考虑使用 std::map<std::string,/*成员函数指针*/> - François Andrieux
1
typeinfo 和一些模板技巧可能可以实现它。如果没有其他人比我先回答,那么我稍后会发布一个答案。 - Silvio Mayolo
C++实际上没有内省能力。我相信可以使用typeinfo来弄出一些东西,但这要么是特定于实现的,要么是一个相对简单的东西需要一个庞大而脆弱的库。有时候拥有一个带有大量“if”的单个函数是可以接受的——不过,老实说,我认为最好的方法是使用unordered_map,它可以与每种类型的初始化/注册代码分离。 - Dúthomhas
有一点运气的话,你可以使用 typeinfo 将类型转换为字符串。但是如果要实现相反的转换,则需要构建某种映射字符串和类型之间关系的表格。if-else 链是这种表格的一种形式,虽然不是最简洁的形式,但手动枚举所有类型是无法避免的。 - n. m.
2
"typeinfo" 不具有可移植性,甚至在同一可执行文件的不同运行中可能无法正常工作。它可能会在某些情况下工作,但一旦您切换编译器或同一编译器的版本,就可能发生问题。 - Eljay
在我进一步思考之前,所有的对象是否都有一个共同的祖先类型?(如果是这样,请在谷歌上搜索“c++对象工厂”。)如果没有,事情会变得更加有趣 :-) - Dúthomhas
1个回答

3

虽然可能有其他的方法不需要使用if语句,但是在某个地方、以某种形式,都必须有代码将字符串和离散类型之间进行转换。这是C++的基本原理:所有对象和表达式的类型必须在编译时得到知晓和确定,这是一个严格而不可变的规则,没有例外,您正在遇到这个基本的、核心的C++原则。

除了if语句之外,其他可能性包括一个关联容器,它将类名映射到闭包,该闭包实例化给定类型的对象或接收任何此“manager”对象作为参数,并使用关联的类名调用管理器的模板方法。

或者可能完全与C++无关,一些脚本读取结构化格式的配置文件,并生成由上述if语句组成的机器人生成的C++代码,然后集成到开发构建系统中,以便在需要时自动构建和重新构建。

但是回答您的问题的简短答案是:不幸的是,C++不会以这种方式工作。obj_str的值直到运行时才能知道。任何C++表达式或语句使用的类型必须在编译时知道,就是这样。没有办法协调这种根本性的分歧。以某种形式,您将需要实现检查和验证每个可能的值的代码和逻辑,并相应地实例化适当的类型。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接