您可以使用字符串(或 c 字符串)作为类型名吗
Can you use a string(or c string) as a typename
我有一个地图加载功能,它使用 ifstream 从文件中获取输入并从中创建对象。
文件可能如下所示:
tree=50,100,"assets/tree.png"
box=10,10,"assets/box.png"
应该创建对象树和框并将值传递给它们的构造函数。我已经弄清楚了值部分,但我不知道如何获取字符串“tree”并创建一个树对象。
是否可以采用字符串(或 c 字符串)并将其用作类型名称?
我尝试过的事情:
将字符串作为模板类型名称传递
#include <string>
struct A {};
template<typename T>
T* createType() {
T* type = new T()
return T;
}
int main() {
std::string tname = "A";
auto* type = createType<tname>;
}
使用使用关键字
#include <string>
template<std::string T>
struct someType {}
struct A {};
struct B {};
using someType<"A"> = A;
using someType<"B"> = B;
int main() {
std::string tname1 = "A";
std::string tname2 = "B";
someType<tname1> typeA;
someType<tname2> typeB;
}
问题:
我似乎找不到关于此的明确答案,但使用字符串作为模板参数似乎存在一些问题。
不知道传一个变量作为模板参数行不行
我不认为你可以转换模板类型(从字符串到类型名)
是否有任何方法可以通过这些方法或其他方法来实现此目的?或者这是不可能的?
没有。据我所知,C++ 中没有规定从任何类型的 in-language 字符串中查找类型。
关于您的其他问题:
- 值模板参数必须是 constexpr:自 C++11 起,您可以使用某些 constexpr 类型的变量作为模板参数
- 显然你可以在 C++17 中使用 constexpr
string_view
模板参数,在 C++20 中使用 constexpr string
模板参数
无论这些其他答案如何,您仍然无法将这些字符串转换为类型。这种操作是动态语言的典型特征,但 C++ 是一种静态类型的编译语言。而且,虽然可以设计一种 可以 在编译时执行那种操作的静态语言,但这不是 C++ 设计所采用的路径。
我觉得问一个问题是合理的:你当初为什么要这样做?可能有更好的方法来完成提示问题的任何内容,但如果没有进一步的信息,很难知道如何提供帮助。
编辑,回应更新的问题:
为了从文件中读取数据结构,您需要自己进行 string-to-type 映射。
通常,您会有一些“驱动程序”对象,您可以在其中注册要从文件创建的类型,然后在从文件中读取时将使用这些类型。
最简单的方法是注册每个类型名称并关联一个回调来构造数据。处理生成的异构数据结构的最直接 object-oriented 方法是从公共 Readable
基础 class.
派生所有类型
注册是您提供要在文件中使用的类型名称的地方。如果您不想在每个注册行中重复类型名称,您可以使用宏来实现——类似于:
#define REGISTER(type) (driver.register(#type, &(type)::construct))
(注意#name
是C预处理器的“string-izing”语法)
我有一个地图加载功能,它使用 ifstream 从文件中获取输入并从中创建对象。
文件可能如下所示:
tree=50,100,"assets/tree.png"
box=10,10,"assets/box.png"
应该创建对象树和框并将值传递给它们的构造函数。我已经弄清楚了值部分,但我不知道如何获取字符串“tree”并创建一个树对象。
是否可以采用字符串(或 c 字符串)并将其用作类型名称?
我尝试过的事情:
将字符串作为模板类型名称传递
#include <string> struct A {}; template<typename T> T* createType() { T* type = new T() return T; } int main() { std::string tname = "A"; auto* type = createType<tname>; }
使用使用关键字
#include <string> template<std::string T> struct someType {} struct A {}; struct B {}; using someType<"A"> = A; using someType<"B"> = B; int main() { std::string tname1 = "A"; std::string tname2 = "B"; someType<tname1> typeA; someType<tname2> typeB; }
问题:
我似乎找不到关于此的明确答案,但使用字符串作为模板参数似乎存在一些问题。
不知道传一个变量作为模板参数行不行
我不认为你可以转换模板类型(从字符串到类型名)
是否有任何方法可以通过这些方法或其他方法来实现此目的?或者这是不可能的?
没有。据我所知,C++ 中没有规定从任何类型的 in-language 字符串中查找类型。
关于您的其他问题:
- 值模板参数必须是 constexpr:自 C++11 起,您可以使用某些 constexpr 类型的变量作为模板参数
- 显然你可以在 C++17 中使用 constexpr
string_view
模板参数,在 C++20 中使用 constexpr
string
模板参数
无论这些其他答案如何,您仍然无法将这些字符串转换为类型。这种操作是动态语言的典型特征,但 C++ 是一种静态类型的编译语言。而且,虽然可以设计一种 可以 在编译时执行那种操作的静态语言,但这不是 C++ 设计所采用的路径。
我觉得问一个问题是合理的:你当初为什么要这样做?可能有更好的方法来完成提示问题的任何内容,但如果没有进一步的信息,很难知道如何提供帮助。
编辑,回应更新的问题:
为了从文件中读取数据结构,您需要自己进行 string-to-type 映射。
通常,您会有一些“驱动程序”对象,您可以在其中注册要从文件创建的类型,然后在从文件中读取时将使用这些类型。
最简单的方法是注册每个类型名称并关联一个回调来构造数据。处理生成的异构数据结构的最直接 object-oriented 方法是从公共 Readable
基础 class.
注册是您提供要在文件中使用的类型名称的地方。如果您不想在每个注册行中重复类型名称,您可以使用宏来实现——类似于:
#define REGISTER(type) (driver.register(#type, &(type)::construct))
(注意#name
是C预处理器的“string-izing”语法)