简体   繁体   English

在C ++函数中传递原始数据类型的最佳实践

[英]Best practice for passing primitive data type in C++ function

I'm writing a function for an avr chip to deserialize a byte stream to primitive types. 我正在为avr芯片编写一个函数,将字节流反序列化为基本类型。 I'd like to do it in as generic a way as possible and was wondering what the best practice would be to determine the type to deserialize. 我想以尽可能通用的方式进行,并且想知道确定反序列化类型的最佳实践是什么。 Ideas I have so far, include: 我到目前为止的想法包括:

Choice A: 选择A:

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

Choice B: 选择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);

Choice C: 选择C:

// Similar to B, but you pass in the type as a parameter
// Function:
TYPE deserialize(uint8_t *in, TYPE);

// Call:
double value = deserialize(in, double);

Choice D: 选择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 */ }
};

Any ideas on the best way to do this? 有关最佳方法的任何想法吗? Perhaps an easier method I overlooked. 也许我忽略了一种更简单的方法。

For starters, C and D are invalid options because types are not valid function arguments; 对于初学者,C和D是无效选项,因为类型不是有效的函数参数; might as well rule them out right now. 不妨现在就把它们排除在外。

Choice B seems like the clear winner here, assuming you aren't concerned about byte ordering or other potential caveats of using a union as you are (it doesn't seem like you would be given the context of this work). 选择B在这里似乎是明显的赢家,假设您不关心字节排序或其他使用联合的潜在警告(看起来您不会得到这项工作的背景)。

One additional thing to consider is having some feedback mechanism to advance your bytestream pointer/index as you deserialize. 另外需要考虑的是在反序列化时使用一些反馈机制来推进字节流指针/索引。 Perhaps you could try something like 也许你可以试试像

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

This has the additional advantage (as I see @Asha beat me to it already!) of allowing you to take advantage of C++ templates' type inference system; 这有额外的优势(正如我看到@Asha已经打败了我!)允许你利用C ++模板的类型推理系统; since the second argument has a known type at the call location, there is no need to explicitly specify a template argument for TYPE. 由于第二个参数在调用位置具有已知类型,因此无需为TYPE显式指定模板参数。

One more option is to return the result as an "out" parameter. 还有一个选项是将结果作为“out”参数返回。 In that case you need not specify the type during the instantiation of the template. 在这种情况下,您无需在模板实例化期间指定类型。 Something like this: 像这样的东西:

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);

A word of caution: 提醒一句:

Using C++ for an AVR is not usually recommended for a number of reasons, and a some things flat out won't work at all -- so be careful to test your code on your target chip before putting any significant time into going down any specific path. 由于多种原因,通常不建议将C ++用于AVR,并且有些事情根本不会起作用 - 因此在将任何特定时间放在任何特定时间之前,请小心测试目标芯片上的代码路径。

But that doesn't mean you have to give up any significant functionality. 但这并不意味着你必须放弃任何重要的功能。 Just adapt your code to suit the available language features. 只需调整您的代码以适应可用的语言功能。

In my view Choice B is the best. 在我看来, 选择B是最好的。 It adds more readability and easy to use. 它增加了可读性和易用性。 Moreover, is TYPE can be some bigger class/struct also ? 而且,TYPE可以是一些更大的类/结构吗? Because you are returning by value from your deserialize() method ! 因为您是通过deserialize()方法按值返回的!

You should use Choice A because: 您应该使用选择A,因为:

  1. It introduces the least complexity. 它引入了最少的复杂性。
  2. Is compatible with both C and C++. 与C和C ++兼容。
  3. Provides straight-forward behavior if the type is not supported. 如果不支持该类型,则提供直接行为。

Note that if you desire the syntax of Choice B, it is always possible to implement that on top of the code for Choice A at a later date (by providing specializations for the different types). 请注意,如果您需要选择B的语法,则始终可以在以后的日期(通过为不同类型提供特化)的代码之上实现该选项。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM