按名称存储和引用变量列表
Store and reference a list of variables by name
我正在尝试创建一个库函数来存储指向各种类型的变量(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()调用中使用的类型生成必要的代码。
如果我枚举所有潜在的数据类型,我可以以一种相对简单(如果笨拙)的方式解决这个问题,无论是通过使用联合和类型枚举,还是通过按类型保留每个变量的单独列表......但我无法弄清楚如何解决它。
有什么想法吗? 我正在使用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);
}
Boost 主要只是标头,因此,除非您的平台缺乏语言级别支持,否则 boost 变体/任何/类型擦除/容器应该开箱即用......
无论如何,如果您仍然想编写自己的类型擦除解决方案,那么这个想法是在抽象接口后面封装"泛型"行为,并让虚拟调度机制调用实际的模板化实现,如下所示:
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()>
,...),无论如何,我希望您了解基本想法...
相关文章:
- C++Boost Asio Pool线程,带有lambda函数和传递引用变量
- 多个"常量引用"变量可以共享同一个内存吗?
- 在 gtest 中初始化堆栈上的引用变量的隔离错误
- C++方法中的引用变量
- 作为赋值(增加引用变量)C++的左操作数所需的左值
- 使用更改此变量的函数在同一行中打印引用变量
- 将延迟变量分配给引用变量
- 如何通过引用获取引用变量的地址?
- 将引用变量传递给函数
- C++中引用变量的内存?
- 按名称存储和引用变量列表
- 返回一个C++引用变量 VS 返回一个变量
- c++ 在 if 语句中分配引用变量
- 引用变量何时合适,为什么?你能解释一下实际的语法和位置吗?
- C++ - 将一个变量分配给另一个变量和将变量分配给引用变量有什么区别?
- 在类范围内声明时,应在 C++14 中引用变量模板
- 当引用变量的引用"死亡"时,它会发生什么?
- 将非按引用变量分配给返回按引用的函数,反之亦然
- 引用变量如何存储在mem中
- 引用变量存储在哪里