假设我有以下一组功能:
typedef uint8_t byte;
inline byte *as_bytes(char *data) {
return reinterpret_cast<byte*>(data);
}
inline byte *as_bytes(std::vector<byte> &v) {
return &v[0];
}
inline byte *as_bytes(QByteArray &a) {
return as_bytes(a.data());
}
inline const byte *as_cbytes(const char *data) {
return reinterpret_cast<const byte*>(data);
}
inline const byte *as_cbytes(const std::vector<byte> &v) {
return &v[0];
}
inline const byte *as_cbytes(const QByteArray &a) {
return as_cbytes(a.data());
}
问题:我可以模拟这些函数,以便constness和指针/引用类型推导能够正常工作吗?我希望看到的结果可能如下:
template<typename T>
inline byte *as_bytes(T data) {
return reinterpret_cast<byte*>(data);
}
template<>
inline byte *as_bytes(std::vector<byte> &v) {
return &v[0];
}
template<>
inline byte *as_bytes(QByteArray &a) {
return as_bytes(a.data());
}
但当然这个代码对我来说不起作用有两个原因:
std::vector
和QByteArray
的特化将无法按预期工作,因为由于函数过载,将始终选择template<typename T> inline byte *as_bytes(T data)
。也许有一些C ++ 11/14/17机制可以解决这些问题并最终得到3个漂亮的函数?
答案 0 :(得分:2)
这可能适合您的需要:
template<typename T>
inline auto as_bytes(T *data) {
return reinterpret_cast<
typename std::conditional<std::is_const<T>{}, const byte*, byte*>::type
>(data);
}
template <typename T>
inline auto as_bytes(T &t) -> decltype(as_bytes(t.data())) {
return as_bytes(t.data());
}
这是如何运作的:
第一个模板函数需要T*
,以便对std::vector
/ QByteArray
(或您可以添加的任何其他类型)的(const)引用永远不会匹配此模板,并使用T
和std::conditional
的组合从std::is_const
推导出常量。
第二个模板函数将匹配具有成员函数T
的任何类型data()
(std::vector
的情况(自C ++ 11以来)和{{ 1}}),并推导出constness,因为QByteArray
有一个const重载。
在第二个函数中使用尾随返回类型将允许您为不提供T::data
方法的类型添加额外的重载,而不会产生歧义。