我有一个可以处理2种不同协议的通信类。该协议由枚举模板变量选择。 现在,2个协议中的1个仅支持2个字节的值,而另一个支持4个字节的值。 通过模板成员函数完成通信。如何更改static_assert所以它需要2或4个字节,具体取决于类的特化(=选择的协议)?
#include <iostream>
#include <math.h>
enum Protocol { P1, P2 };
template <Protocol P>
class Communicator {
public:
template <typename T>
void communicate(T arg) {
static_assert(sizeof(arg) <= sizeof(float), "argument size must be <= 4 bytes");
float value = (float)arg;
uint8_t length = sizeof(arg); //length in bytes
_communicate(value, length);
}
void _communicate(float f, uint8_t length) {
std::cout << f;
}
};
编辑:我可以选择1个答案为正确。虽然我从罗伊那里学到了很多东西,但我选择了MM的答案,因为它让事情变得尽可能简单。 (但两者都赞成)
答案 0 :(得分:4)
有几种方法可以解决这个问题......这里有一个:
template<Protocol P>
size_t value_size();
template<> size_t value_size<P1>() { return 2; }
template<> size_t value_size<P2>() { return 4; }
// ... inside your other function
static_assert(sizeof(arg) <= value_size<P>(),
答案 1 :(得分:2)
这是一种不同的方法
#include <iostream>
#include <math.h>
#include <cstdint>
// enum Protocol { P1, P2 }; // let's use types with traits instead.
struct P1
{
constexpr static const int protocol_id = 1;
//^^ or maybe use an enum
// type, this may need refactoring
// to fit your code and style.
using data_type = uint16_t; //< or whatever your 2-byte datatype is.
// can add more data traits and even static member functions here
// you could also add protocol specific non-static data if you add a
// P1 data member to your Communicator class.
// A struct with traits is a very good entry point for many compile-time
// polymorphism techniques.
};
struct P2
{
constexpr static const int protocol_id = 2;
using data_type = uint32_t; //< or whatever your 4-byte datatype is.
};
template <typename _Proto>
class Communicator {
public:
using data_type = typename _Proto::data_type;
constexpr static const int proto_id = typename _Proto::protocol_id;
public:
void communicate(data_type arg) // we can use the trait from either P1 or P2
{
float value = (float)arg;
uint8_t length = sizeof(data_type); //length in bytes
_communicate(value, length);
}
void _communicate(float f, uint8_t length)
{
std::cout << f;
}
};
这里是转换枚举的代码(如果那是你已经拥有的一个类。
enum protocol_t { p1, p2 };
template <protocol_t _p> struct Protocol {};
// simply derive the template specialization from the desired type
template <> struct Protocol<p1> : P1 {};
// simply derive the template specialization from the desired type
template <> struct Protocol<p2> : P2 {};
您也可以从P1,P2派生,以帮助组织代码。
struct P1
{
// ... + specialized functions:
void _communicate(value_type x) { ... } // that you'll call from Communicator
void _communicate(const value_type* begin, const value_type* end) { ... }
};
struct P2 { /* same thing */ };
template <typename _Proto>
class Communicator : _Proto // < can control visibility here.
{ ... };