我有一个字符串变量,其中包含结构的名称。此结构在头文件中声明。我想基于结构名称的值创建一个结构的对象,该结构名称保存在C ++的字符串变量中。
struct myStruct{
int a;
char b;
};
string structName = "myStruct";
// Instantiate a structure variable [like this: "struct myStruct"]
有人可以帮我这个吗?
您正在寻找的功能称为introspection。这是C ++没有的东西。所以你应该按顺序回退:
这是一个黑客的想法:
using result_type = /* some type, possibly void */;
std::unique_ptr<result_type> factory(std::string const& kind)
{
if (kind == "alice") return new alice;
if (kind == "bob") return new bob;
// ...
return nullptr;
}
在C ++中,无法通过在运行时确定的名称创建类的实例。 C ++对reflect的能力很弱。
但是,您可以自己构建支持。这里的想法是为工厂函数创建一个name-string映射,该函数返回该类型的实例。返回的实例需要包含在std::any
中,因为C ++ - 作为强类和静态类型的语言 - 不能让返回类型在运行时确定。
有一个函数add_factory
,必须为您希望能够使用该名称实例化的所有类型调用它。还有一个辅助宏,它像所有宏一样,因魔法而起作用。
auto& factories() {
static std::unordered_map<std::string, std::any(*)()> factories;
return factories;
}
template<class T>
void
add_factory(const char* name) {
// further development: take function as argument so that
// non-default-constructible classes can be supported
factories()[name] = []() -> std::any {
return T{};
};
}
std::any
create(const char* name)
{
const auto& f = factories();
if (f.find(name) != f.end())
return f.find(name)->second();
throw std::runtime_error("I haven't heard of this type");
}
// don't use this macro in header files
#define ADD_FACTORY(name) namespace { auto dummy_##name = (add_factory<name>(#name), 0); }
// ----- usage -----
struct a {
int i;
};
ADD_FACTORY(a)
struct b {
double d;
};
ADD_FACTORY(b)
// factories are not limited to classes
ADD_FACTORY(int)
int main()
{
std::any instance = create("a");
assert(std::any_cast<a>(&instance));
}