如何使用type_traits或模板函数专门化来整合模板方法
how do I use type_traits or template function specialization to consolidate template methods
我试图从类似于下面所示的类中合并许多非常相似的函数方法,我认为有效实现这一点的最佳方法是通过使用模板与模板函数专门化或类型特征相结合。我是模板专业化和类型特征的新手,但我理解基本概念,这就是为什么我在细节上要求一些指导。无论如何,作为起点,我的类是一个智能缓冲类,它有许多类似于下面列出的方法签名。
class OldSafeBuffer {
public:
intmax_t writeAt(const intmax_t& rIndex, const uint32_t val32);
intmax_t writeAt(const intmax_t& rIndex, const int32_t val32);
intmax_t readFrom(const intmax_t& rIndex, uint32_t& rVal32);
intmax_t readFrom(const intmax_t& rIndex, int32_t& rVal32);
intmax_t writeAt(const intmax_t& rIndex, const uint16_t val16);
intmax_t writeAt(const intmax_t& rIndex, const int16_t val16);
intmax_t readFrom(const intmax_t& rIndex, uint16_t& rVal16);
intmax_t readFrom(const intmax_t& rIndex, int16_t& rVal16);
intmax_t read(uint32_t& rVal32);
intmax_t read(int32_t& rVal32);
intmax_t read(uint16_t& rVal16);
intmax_t read(int16_t& rVal16);
protected:
// Actual memory storage.
std::unique_ptr<char[]> mBuffer;
// Buffer length
intmax_t mBufferLength;
// Represents the largest byte offset referenced.
// Can be used to retrieve written length of buffer.
intmax_t mHighWaterMark;
// If set, caller wanted to pack data in network-byte-order.
bool mPackNBO;
// Set on construction, determines whether value needs to be byte-swapped.
bool mSwapNeeded;
// Used for file compatibility
intmax_t mPosition;
};
我认为这将是一个完美的候选转换使用模板函数,因为这些函数非常相似,我有很多重复的代码在每个方法。两种方法的区别主要在于符号和16位或32位值参数的大小。
无论如何,为了巩固readFrom方法,我把下面的方法放在一起。我也为write方法做了类似的事情。这些都显示在编译的实例中。
/**
* Read value (signed or unsigned) from buffer at given byte offset.
*
* @param rIndex [in]
* @param rVal [out]
*
* @return BytesRead or -1 on error
*/
template <typename T>
inline intmax_t readFrom(const intmax_t& rIndex, T& rVal)
{
if ((rIndex + static_cast<intmax_t>(sizeof(T))) <= mBufferLength) {
T* pVal = (T *)&mBuffer[rIndex];
rVal = *pVal;
// @JC Partial Template Specialization for 16 bit entities?
if (sizeof(rVal) > sizeof(int16_t)) {
SWAP32(rVal);
} else {
SWAP16(rVal);
}
mPosition = rIndex + sizeof(T);
return sizeof(rVal);
}
return -1;
}
从我的评论中可以看出,我还需要知道'T&以决定是对该参数执行SWAP32还是SWAP16。这就是为什么我认为type_traits会更有用,而不是必须在运行时检查来比较参数的大小。
我认为我是在正确的轨道上,但我无法弄清楚如何使用type_traits来检查和做某些事情取决于参数类型。我认为我可以选择使用模板方法专门化对16位参数做特殊的事情,但我认为这不会节省太多的精力,因为我还必须专门化16位参数类型的有符号和无符号变体(假设非专门化版本适用于32位值参数)。任何帮助弄清楚这将是非常感激的。
你可以这样写:
template<typename T, std::size_t N = sizeof(T)> struct Swap;
template<typename T> struct Swap<T, 1> {
void operator() (T&) const { /* Do nothing*/ }
};
template<typename T> struct Swap<T, 2> {
void operator() (T& val) const { SWAP16(val); }
};
template<typename T> struct Swap<T, 4> {
void operator() (T& val) const { SWAP32(val); }
};
然后命名为:
Swap<T>()(rVal);
所以在上下文中:
if (sizeof(T) > sizeof(int16_t)) {
SWAP32(val);
} else {
SWAP16(val);
}
可以写成
Swap<T>()(val);
您可以使用模板专门化来执行专门化的swap
函数,如下面的示例:
template<typename T>
struct Swap;
template<>
struct Swap<int16_t> {
static void swap(int16_t val) { SWAP16(val); }
};
template<>
struct Swap<int32_t> {
static void swap(int32_t val) { SWAP32(val); }
};
那么你可以在代码中这样调用它:
template <typename T>
inline intmax_t readFrom(const intmax_t& rIndex, T& rVal)
{
if ((rIndex + static_cast<intmax_t>(sizeof(T))) <= mBufferLength) {
T* pVal = (T *)&mBuffer[rIndex];
rVal = *pVal;
Swap<T>::swap(rVal);
mPosition = rIndex + sizeof(T);
return sizeof(rVal);
}
return -1;
}
您可以为您的4种类型定义swap方法:
inline void swap_endianess(int16_t& value) { SWAP16(value); }
inline void swap_endianess(uint16_t& value) { SWAP16(value); }
inline void swap_endianess(int32_t& value) { SWAP32(value); }
inline void swap_endianess(uint32_t& value) { SWAP32(value); }
,并让模板函数分派到正确的那个。
所以不用
if (sizeof(T) > sizeof(int16_t)) {
SWAP32(val);
} else {
SWAP16(val);
}
就叫
swap_endianess(val);
相关文章:
- 尝试根据类中 typedef 的存在来专门化模板函数
- 如何基于模板化类的基类专门化成员函数
- 专门化模板覆盖函数/避免对象切片
- 如何使用模板化类专门化模板化函数?
- 线程 std::调用未知类型,无法专门化函数错误
- 如何在编译时专门化大型模板函数中的小部分
- 模板函数,其中一个参数需要专门化,而另一个不需要
- 错误 C2893 无法专门化函数模板'unknown-type std::invoke(_Callable &&,_Types &&...)'
- 从 std 命名空间中专门化函数模板的想法有多糟糕?
- 使用decltype尾部返回类型专门化函数模板
- 为模板化派生类专门化函数模板
- C++模板-专门化函数
- 在单独的.cpp文件中专门化函数模板
- 创建专门化函数模板的最佳方法是什么?
- 用泛型返回类型专门化函数
- 可以将运行时确定的模板参数传递给专门化函数吗?
- 根据调用方/上下文专门化函数的行为
- 专门化函数从其他函数调用
- c++中专门化函数模板的语法
- c++对枚举的专门化函数