我正在尝试创建一个库函数来存储指向各种类型变量(int,char,String等)的指针,然后通过引用它们的名称来打印它们的值。
所以:
int a;
const char *b;
String c;
storeVar("a", &a);
storeVar("b", &b);
storeVar("c", &c);
以后:
printVar("a");
printVar("b");
printVar("c");
这里的技巧是我不想枚举用户可能调用的所有潜在类型;也就是说,我想根据我在storeVar()调用中使用的类型,使用模板在编译时生成必要的代码。
如果我通过使用union和类型枚举枚举所有可能的数据类型,或者通过按类型保持每个变量的单独列表,我可以以相对简单(如果笨重)的方式解决这个问题...但我可以弄清楚如何一般地解决它。
有什么想法?我正在开发一个Arduino平台,所以我比在PC上更受限制(例如Boost可能不是一个选项)。
此解决方案基于Massimiliano Janes提供的代码,正在运行。不幸的是,unordered_map在整个Arduino平台上都不可用,所以我可能无法使用它。但是,这只是一个存储细节,我相信无论变量如何存储,这种方法都会有效。
// rst.h
#include <unordered_map>
class Rst {
private:
struct variable
{
virtual void print_me() const = 0;
};
template<typename T>
struct variable_of_type: variable
{
T *var;
variable_of_type(T *v) : var{v} { }
void print_me() const override {
Serial.println(*var);
}
};
public:
template<typename T>
void store_var(const char *name, T *v) {
varList[name] = new variable_of_type<T>(v);
}
void print(const char *name) {
varList[name]->print_me();
}
private:
std::unordered_map<const char*, variable*> varList;
};
#include "rst.h"
Rst rst;
int q;
int a = 0;
const char* b = "hallo";
void setup()
{
Serial.begin(115200);
Serial.println("=====");
rst.store_var("q", &q);
rst.store_var("a", &a);
rst.store_var("b", &b);
q = 10;
rst.print("q");
rst.print("a");
rst.print("b");
q=15;
rst.print("q");
}
void loop() {
delay(1000);
}
答案 0 :(得分:1)
Boost主要是标题,因此,除非您的平台缺乏语言级支持,否则boost / any / type-erasure / containers应该可以为您提供开箱即用的功能......
无论如何,如果您仍想编写自己的类型擦除解决方案,那么我们的想法是将抽象接口背后的“通用”行为封装起来,让虚拟调度机制调用实际的模板化实现,例如: / p>
struct variable
{
virtual ~variable() = default;
virtual void print_me() const = 0;
};
template<typename T>
struct variable_of_type:
variable
{
T const& var;
variable_of_type(T const& v)
:var{v}{}
virtual void print_me() const override
{ std::cout << var << std::endl; }
};
template<typename T>
auto make_var(T const& v) // beware of v's lifetime !
{ return std::make_unique<variable_of_type<T>>(v); }
int main()
{
auto a = 0;
auto b = std::string{"hallo"};
auto vars = std::unordered_map<std::string,std::unique_ptr<variable>>{};
vars["a"] = make_var(a);
vars["b"] = make_var(b);
vars["a"]->print_me();
vars["b"]->print_me();
}
更准确地说,真正的类型擦除解决方案会隐藏一些常规类型背后的unique_ptr层(例如,请参阅std::any
,std::function<void()>
,...),无论如何,我希望你有基本的想法...