使用C 中的字符串从类名称创建对象
Create object from class name using a string in C++
我有一个Base
类:
class Base() {
public:
Base(int, int);
~Base();
};
我有多个从Base
继承的类:
class childA : public Base {
public:
childA(int, int, string);
~childA();
};
childA::childA(int x, int y, string str) : Base (x, y)
{
// do something here
}
childB
,childC
,等等
我想知道是否可以使用字符串创建childA
,childB
或childC
。我听说过variadic tempaltes,但我真的不明白如何使用它。
variadic模板是一个模板,可以采用任何类型的任意数量的模板参数。自C语言的黎明(例如,printf函数),然后是宏和现在 - 模板。
以来,这两个函数都可以是变性您可以这样声明:
template<typename... Arguments> class Variadic;
然后使用任意数量的参数进行专业化,包括零:
Variadic<double> instance;
Variadic<double, std::string> instance;
Variadic<> instance;
然后您可以使用称为参数包的参数列表,例如:
template<typename... Arguments> void SampleFunction(Arguments... parameters);
就像在variadic函数的情况下一样,参数包可以在具体参数之前:
template<typename First, typename... Rest> class BunchOfValues;
stl: std::tuple
中有variadic模板的经典示例。一些编译器不完全支持此功能或根本不支持此功能,在他们的情况下,元组是通过元编程和宏定义实现的。C 没有直接的方法可以从列表中选择特定参数,就像使用variadic函数可以使用。可以使用递归在一个方向上迭代它们:
template<typename T> foo(T first)
{
// do something;
}
template<typename T, typename U, typename ... Args> foo(T first, U second, Args... Rest)
{
// do something with T
foo(second, Rest...);
}
通常迭代将依靠函数过载,或者 - 如果函数一次可以一次选择一个参数,则使用愚蠢的扩展标记:
template<typename... Args> inline void pass(Args&&...) {}
可以使用如下:
template<typename... Args> inline void expand(Args&&... args) {
pass( some_function(args)... );
}
expand(42, "answerswer", true);
将扩展到以下内容:
pass( some_function(arg1), some_function(arg2), some_function(arg3) etc... );
使用此"通过"功能是必要的,因为参数包的扩展是通过将函数调用参数分开的逗号来进行的,逗号不等于逗号运算符。some_function(args)...;
永远不会起作用。而且,只有在some_function的返回类型没有无效的情况下,以上解决方案才能起作用。此外,某些函数调用将以未指定的顺序执行,因为函数参数的评估顺序是未定义的。为了避免未指定的订单,可以使用支撑封闭的初始化器列表,以确保严格的左右评估顺序。为了避免需要非空隙返回类型,逗号运算符可以始终在每个扩展元素中产生1个。
struct pass {
template<typename ...T> pass(T...) {}
};
pass{(some_function(args), 1)...};
参数包中的参数数可以通过sizeof...(args)
表达式确定。
创建使用调用名称的初始化器时,只有在编写代码时定义名称时才有可能。可以使用的预处理器中的刺刺操作员#,例如
#define printstring( x ) printf(#x "n")
printstring( This a dumb idea );
将生成代码(假设C 自动加入字符串文字):
printf("This a dumb idea n")
您可以声明这样的内容:
template<typename T> class moniker
{
public:
moniker(const char* tname);
}
#define declare_moniker(type, name) moniker<type> name(#type)
variadic宏定义和variadic模板如何相互作用?我不知道。我手头的编译器失败了,但不是C 11。如果有兴趣,请尝试。
根据编译器设置,可能会有typeid操作员的支持。
const std :: type_info&amp;ti1 = typeid(a);
std :: type_info获取方法名称(),但是字符串返回的字符串取决于:http://en.cppreference.com/w/cpp/types/type/type_info/name
在C 14中您可以创建一些辅助结构来确定您在编译时传递的每个字符串的字符字符,并将其转发到类型。但是,您通过的字符串需要存储在linkage的变量中,以使编译器将其用作非类型模板参数:
#include <utility>
#include <type_traits>
template <char... Cs>
struct string_literal { };
template <class T, T &, class>
struct make_string_literal_impl;
template <class T, T &Cs, std::size_t... Is>
struct make_string_literal_impl<T, Cs, std::index_sequence<Is...>> {
using type = string_literal<Cs[Is]...>;
};
template <class T, T &>
struct make_string_literal;
template <class T, std::size_t N, T (&Cs)[N]>
struct make_string_literal<T[N], Cs>: make_string_literal_impl<T[N], Cs, std::make_index_sequence<N>> {
};
struct Base {
Base(int, int) { }
~Base() { }
};
template <class>
struct Child: Base {
using Base::Base;
};
constexpr char const str[] = "abc";
int main() {
Child<make_string_literal<decltype(str), str>::type> c(1, 1);
}
[live demo]
- 使用基类指针创建对象时,缺少派生类析构函数
- 如何创建对象函数指针C++映射?
- C++创建对象数组
- 在 C++ 的 Switch Case 中创建对象后对对象调用方法
- 如何获取在 main() 函数中构造的类的创建对象?
- 基于文件中的条目创建对象
- 错误:创建对象后无法分配区域
- C++ 通过输入创建对象
- 如何从标准::string_view正确创建标准::字符串?
- 堆还是堆栈用于创建对象?
- 使用 C++ 创建对象数组
- 在堆或堆栈上分配的动态创建的字符串 - C
- 使用unique_ptr创建对象
- C++递归地在类构造函数中创建对象
- 通过向构造函数其他对象引用页面来创建对象
- 使用C 中的字符串从类名称创建对象
- 从字符串创建对象 (C++)
- 可以使用 cout 打印,但不能使用相同的对象创建新字符串?
- 我如何创建boost::posix_time::ptime对象从使用QDateTime ISODate格式创建的字符串
- 根据 C++ 中的字符串创建对象