编写二进制文件模板功能
writing Binary File template functions
我做了一些功能来编写和读取class到二进制文件。
如果参数是类,我只想打电话给第一个writeElement
函数。
然后,我想在一个函数中具有int, double, size_t
的其他功能。必须有一种更好的方法来做到这一点,我不必为所有不同类型创建一个新功能。
template <class T>
inline void writeElement(ostream& out, T target) { target.write(out); }
inline void writeElement(ostream& out, int target) { out.write((char*)&target, sizeof(int)); }
inline void writeElement(ostream& out, double target) { out.write((char*)&target, sizeof(double)); }
inline void writeElement(ostream& out, size_t target) { out.write((char*)&target, sizeof(size_t)); }
inline void writeElement(ostream& out, const string str)
{
size_t size = str.size();
writeElement(out, size);
out.write(&str[0], size);
}
template <class T>
inline void writeElement(ostream& out, vector<T> vector)
{
size_t size = vector.size();
writeElement(out, size);
for (auto &element : vector)
{
writeElement(out, element);
}
}
class Header
{
public:
string sig;
double version;
public:
void read(istream& in)
{
readElement(in, sig);
readElement(in, version);
}
void write(ostream& out)
{
writeElement(out, sig);
writeElement(out, version);
}
};
我想有很多方法可以做到这一点。
我在设置 constexpr
value
template <typename>
struct foo { static constexpr std::size_t value { 0U }; };
template <>
struct foo<int> { static constexpr std::size_t value { 1U }; };
template <>
struct foo<double> { static constexpr std::size_t value { 1U }; };
template <>
struct foo<std::size_t> { static constexpr std::size_t value { 1U }; };
template <>
struct foo<std::string> { static constexpr std::size_t value { 2U }; };
因此,您可以使用foo<T>::value
template <typename T>
inline typename std::enable_if<0U == foo<T>::value>::type
writeElement (std::ostream & out, T const & t)
{ std::cout << "generic case" << std::endl; }
template <typename T>
inline typename std::enable_if<1U == foo<T>::value>::type
writeElement (std::ostream & out, T const & t)
{ std::cout << "int, double, size_t case" << std::endl; }
template <typename T>
inline typename std::enable_if<2U == foo<T>::value>::type
writeElement (std::ostream & out, T const & t)
{ std::cout << "string case" << std::endl; }
template <typename T>
inline void writeElement (std::ostream & out, std::vector<T> const & v)
{ std::cout << "vector case" << std::endl; }
以下是一个完整的工作示例
#include <set>
#include <vector>
#include <iostream>
#include <type_traits>
template <typename>
struct foo { static constexpr std::size_t value { 0U }; };
template <>
struct foo<int> { static constexpr std::size_t value { 1U }; };
template <>
struct foo<double> { static constexpr std::size_t value { 1U }; };
template <>
struct foo<std::size_t> { static constexpr std::size_t value { 1U }; };
template <>
struct foo<std::string> { static constexpr std::size_t value { 2U }; };
template <typename T>
inline typename std::enable_if<0U == foo<T>::value>::type
writeElement (std::ostream & out, T const & t)
{ std::cout << "generic case" << std::endl; }
template <typename T>
inline typename std::enable_if<1U == foo<T>::value>::type
writeElement (std::ostream & out, T const & t)
{ std::cout << "int, double, size_t case" << std::endl; }
template <typename T>
inline typename std::enable_if<2U == foo<T>::value>::type
writeElement (std::ostream & out, T const & t)
{ std::cout << "string case" << std::endl; }
template <typename T>
inline void writeElement (std::ostream & out, std::vector<T> const & v)
{ std::cout << "vector case" << std::endl; }
int main ()
{
writeElement(std::cout, std::set<int>{});
writeElement(std::cout, 0);
writeElement(std::cout, 0.0);
writeElement(std::cout, std::size_t{});
writeElement(std::cout, std::string{"0"});
writeElement(std::cout, std::vector<int>{});
}
然后我想在
int, double, size_t
中具有其他功能 一个功能。必须有一种更好的方法来做到这一点,我不应该 必须为所有不同类型创建一个新功能。
为此,您可能希望使用"特质" class-template ,并且您有一个函数为您完成工作。
//Primary templates for every other object
template<typename T, typename = void>
struct WriteHelper{
static void write(ostream& out, T target){
target.write(out);
}
};
//Specialization for integral types
template<typename T>
struct WriteHelper<T, std::enable_if_t<std::is_arithmetic<T>::value >>{
static void write(ostream& out, T target){
out.write((char*)&target, sizeof(T));
}
};
//Specialization for std::string
template<typename T>
struct WriteHelper<T, std::enable_if_t<std::is_same<std::string, T>::value >>{
static void write(ostream& out, T target){
size_t size = str.size();
writeElement(out, size);
out.write(&str[0], size);
}
};
并使用为:
template<typename T, typename X = std::decay_t<T>>
inline void writeElement(ostream& out, T&& target){
WriteHelper<X>::write(out, std::forward<T>(target));
}
只需将Sfinae用于班级,本机和其他特殊定义类型,例如:
template <typename T, typename std::enable_if < std::is_class<T>::value, void >::type* = nullptr >
inline void writeElement( T )
{
std::cout << "Class write" << std::endl;
}
template <typename T, typename std::enable_if<!std::is_class<T>::value, void>::type* = nullptr>
inline void writeElement( T )
{
std::cout << "Native type" << std::endl;
}
template <typename T>
inline void writeElement( const std::vector<T>& )
{
std::cout << "vector" << std::endl;
}
inline void writeElement( std::string )
{
std::cout << "string" << std::endl;
}
class A{};
int main()
{
writeElement( A{} );
writeElement( 1 );
writeElement( std::vector<int>{1,2,3,4} );
writeElement( std::string{"Hallo"});
}
因此,每个"本机类型"都可以使用一个模板函数来处理。您还应该去看指针,因为您无法以这种方式处理指针,因为您不能用指针本身将长度延长。
也使用sfinae并在
中分裂具有
void write(ostream&)
方法的类:template <typename T> typename std::enable_if<std::is_same<decltype(&T::write), void(T::*)(ostream&)>::value, void>::type writeElement(ostream& out, T& target) { target.write(out); }
注意最好通过引用通过类,以防止复制。
算术类型(
int
,double
,size_t
等(:template <typename T> typename std::enable_if<std::is_arithmetic<T>::value, void>::type writeElement(ostream& out, T target) { out.write((char*)&target, sizeof(T)); }
std::is_scalar
如果要包括枚举。和
std::string
和std::vector<T>
inline void writeElement(ostream& out, const string& str) { const size_t size = str.size(); writeElement(out, size); out.write(str.data(), size); // NOTE: Accessing &str[0] if the `.size() == 0` is *Undefined behavior*, use `std::string::data()` insetad } template <class T> inline void writeElement(ostream& out, const vector<T>& vector) { const size_t size = vector.size(); writeElement(out, size); for (const auto &element : vector) { writeElement(out, element); } }
NOTE 访问
string
S&str[0]
如果其尺寸为零,则导致不确定的行为
相关文章:
- 正在读取二进制文件(is_open)
- 在C++中将类(带有Vector成员)保存为二进制文件
- 如何从二进制文件中读取字符串
- 保存/加载大量短数组到二进制文件
- 从二进制文件中读取整数数组
- Android 在编译二进制文件时重建静态库
- 在 C++ 中将双精度变量写入二进制文件
- clang 的 libFuzzer 可以在同一二进制文件中测试超过 1 个 API 吗?
- C++:实际上不是从二进制文件中读取
- 如何从二进制文件中的给定符号中获取调用程序图
- 将内部带有矢量的结构保存/读取到二进制文件中
- 编译多个C++文件.调用二进制文件以运行代码
- 如何使用位字段将数据从二进制文件复制到结构中?
- uint8_t同一二进制文件的不同十进制值
- C++单个生成文件多个二进制文件
- 尝试将数字写入二进制文件时引发异常
- MPI 二进制文件 I/O 基本功能和性能问题
- 编写二进制文件模板功能
- 将功能写入二进制文件
- 需要帮助调试简单的更新二进制文件的功能