按名称存储和引用变量列表

时间:2018-01-27 09:44:21

标签: c++ arduino

我正在尝试创建一个库函数来存储指向各种类型变量(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);
}

1 个答案:

答案 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::anystd::function<void()>,...),无论如何,我希望你有基本的想法...