C++ 在C++;功能

C++ 在C++;功能,c++,templates,serialization,avr,C++,Templates,Serialization,Avr,我正在为avr芯片编写一个函数,将字节流反序列化为基本类型。我想以尽可能通用的方式来做这件事,并且想知道确定反序列化类型的最佳实践是什么。到目前为止,我的想法包括: 选择A: // Just write a function for each type double deserialize_double(uint8_t *in) { } 选择B: // Use a template, and pass the type in when calling // Function: template

我正在为avr芯片编写一个函数,将字节流反序列化为基本类型。我想以尽可能通用的方式来做这件事,并且想知道确定反序列化类型的最佳实践是什么。到目前为止,我的想法包括:

选择A:

// Just write a function for each type
double deserialize_double(uint8_t *in) { }
选择B:

// Use a template, and pass the type in when calling
// Function:
template <typename TYPE>
TYPE deserialize(uint8_t *in) {
  union {
    TYPE real;
    uint8_t base[sizeof(TYPE)];
  } u;

  for (unsigned int i = 0; i < sizeof(TYPE); i++) {
    u.base[i] = in[i];
  }
  return u.real;
}

// Call:
double value = deserialize<double>(in);
选择D:

// Use a templated class. My main issue with this is I was hoping 
// to re-use the same object for deserializing multiple types.
template <typename TYPE>
class Serializer {
  public void serialize(uint8_t *out, TYPE value) { /* code */ }
  public TYPE deserialize(uint8_t *int) { /* code */ }
};
//使用模板化类。我的主要问题是我希望
//重复使用同一对象反序列化多个类型。
模板
类序列化程序{
public void序列化(uint8_t*out,类型值){/*code*/}
公共类型反序列化(uint8_t*int){/*code*/}
};

有什么好办法吗?也许我忽略了一个更简单的方法。

还有一个选项是将结果作为“out”参数返回。在这种情况下,您不需要在模板实例化期间指定类型。大概是这样的:

template <typename TYPE>
void deserialize(uint8_t *in, TYPE& out) {
  union {
    TYPE real;
    uint8_t base[sizeof(TYPE)];
  } u;

  for (unsigned int i = 0; i < sizeof(TYPE); i++) {
    u.base[i] = in[i];
  }
  out = u.real;
  return;
}

// Call:
double value = 0;
deserialize(in, value);
模板
void反序列化(uint8_t*in、TYPE和out){
联合{
类型real;
uint8_t基底[sizeof(类型)];
}u;
for(无符号整数i=0;i
对于初学者,C和D是无效的选项,因为类型不是有效的函数参数;最好现在就把他们排除在外

假设您不关心字节顺序或其他使用联合的潜在警告(看起来您不会了解这项工作的上下文),那么选择B似乎是这里的明显赢家

另一个要考虑的事情是在你反序列化时使用一些反馈机制来推进你的字节流指针/索引。也许你可以试试这样的东西

template <typename TYPE>
int deserialize(uint8_t *in, TYPE& value) {
    union {
        TYPE real;
        uint8_t base[sizeof(TYPE)];
    } u;

    for (unsigned int i = 0; i < sizeof(TYPE); i++) {
        u.base[i] = in[i];
    }
    value = u.real;
    return sizeof(TYPE);
}

// Call:
double foo, bar;
int baz;
in += deserialize(in, foo);   // Implicit double deserialize
in += deserialize(in, bar);   // Implicit double deserialize
in += deserialize(in, baz);   // Implicit int deserialize
模板
int反序列化(uint8_t*in、类型和值){
联合{
类型real;
uint8_t基底[sizeof(类型)];
}u;
for(无符号整数i=0;i

<>这有额外的优势(正如我看到的Asha已经击败了我),它允许你利用C++模板的类型推理系统;由于第二个参数在调用位置具有已知类型,因此无需显式指定类型的模板参数。

在我看来,选择B是最好的。它增加了可读性和易用性。 而且,类型是否也可以是某个更大的类/结构?因为您是从
反序列化()
方法按值返回的

警告一句:

使用C++来处理AVR通常不需要考虑很多原因,有些事情是完全不可行的,所以在把任何重要的时间放到任何特定的路径之前,要小心测试你的目标芯片上的代码。
但这并不意味着你必须放弃任何重要的功能。只需调整代码以适应可用的语言功能。

您应该使用选项A,因为:

  • 它引入了最小的复杂性
  • 与C和C++兼容,
  • 如果不支持该类型,则提供直接行为

  • 注意,如果您希望选择B的语法,那么在以后的日期(通过为不同类型提供专门化)时,总是可以在代码顶部实现它。

    当查看这里的大图时,将这些东西放在C++ >代码> IoSturiS> 界面中不是更好吗?而不是笨重的C型函数?同样的
    template
    d方式将是可能的,但语法最终会更容易理解。@rubenvb-虽然空间有限,我不想接近iostream的复制,但我喜欢遵循它们的函数命名和约定。为什么那些
    for(unsigned int I=0;I
    循环在这个问题和答案中如此流行?这难道不是毫无理由地复制最多8个字节,还是希望编译器优化复制过程?不应该只做一个<代码>返回((type *)in)< /C> >实现相同的事情(或者也许是代码>返回(STATICOSTCAST(IN))< /COD>如果你坚持C++语法)我跟你和Asha的想法传递。我喜欢在函数中返回偏移量。最后的结果可以看出,我不想劫持这个问题,但是你有没有提到C++对于AVR是不可取的?我正在编辑一个项目,它在AVR上广泛使用C++(像AtMaG328 P),看起来不错。我很好奇该注意什么。
    template <typename TYPE>
    int deserialize(uint8_t *in, TYPE& value) {
        union {
            TYPE real;
            uint8_t base[sizeof(TYPE)];
        } u;
    
        for (unsigned int i = 0; i < sizeof(TYPE); i++) {
            u.base[i] = in[i];
        }
        value = u.real;
        return sizeof(TYPE);
    }
    
    // Call:
    double foo, bar;
    int baz;
    in += deserialize(in, foo);   // Implicit double deserialize
    in += deserialize(in, bar);   // Implicit double deserialize
    in += deserialize(in, baz);   // Implicit int deserialize