我希望所有的数据保存和加载都经过相同的功能,以减少错误的机会。为此,我使用了许多模板(以及许多函数重载)。它可以正常工作,现在我的代码更加简洁了,但是我无法使用const进行保存(因为它要通过与加载器相同的功能进行操作,在加载器中,数据保持为非const)。
我想正确地使用const,因此这里是尝试使简单版本正常工作的尝试,其中std :: ifstream的数据(在这种情况下为std :: vector)是非const的,否则为const:
#include <iostream>
#include <fstream>
#include <vector>
template <class Foo>
void Overload(const Foo & foo)
{
std::cout << "went to const" << std::endl;
}
template <class Foo>
void Overload(Foo & foo)
{
std::cout << "went to non-const" << std::endl;
}
template <class StreamType, typename... Arguments>
void ReadOrWrite (
/* for 1st argument */ StreamType & filestream,
/* type for 2nd argument */ typename std::conditional<
/* if */ std::is_same<StreamType, std::ifstream>::value,
/* then */ std::vector<Arguments...>,
/* else */ const std::vector <Arguments...>
>::type
/*2nd argument name */ & vector
)
{
Overload(vector);
}
int main ()
{
std::ofstream output_filestream;
std::ifstream intput_filestream;
std::vector<int> vector;
ReadOrWrite(output_filestream, vector);
ReadOrWrite(intput_filestream, vector);
return 0;
}
我知道如果我编辑对此的函数调用,它将正确编译/运行:
ReadOrWrite<std::ofstream, int>(output_filestream, vector);
ReadOrWrite<std::ifstream, int>(intput_filestream, vector);
但是我不希望函数的用户在函数调用期间需要列出类型。
是否有一种干净的方法可以执行我的建议?
最好的建议是提供两个分离的功能,因为无论您发送哪种类型的读和写操作都是两个不同的操作。例如,输入和输出都可能是fstream
。仅凭类型系统,您就无法知道意图。决定读写是通常的意图,而很少将它们嵌入到类型系统中。
由于保存和加载是不同的操作,因此应该是不同的功能(可能在它们之间共享代码)
如果您确实想要同时执行这两种功能并在类型之间进行切换的功能,那么我建议限制输入或输出的功能:
// input streams
template <class StreamType, typename... Arguments,
std::enable_if_t<std::is_base_of_v<std::ostream, StreamType>, int> = 0
>
void ReadOrWrite (
StreamType & filestream,
std::vector<Arguments...> const& vector
) {
Overload(vector);
}
// output streams
template <class StreamType, typename... Arguments,
std::enable_if_t<std::is_base_of_v<std::istream, StreamType>, int> = 0
>
void ReadOrWrite (
StreamType& inputstream,
std::vector<Arguments...>& vector
) {
Overload(vector);
}
由于第二个比第一个更专业,因此只要流为std::istream
并且向量是可变的,都将采用它。否则,将采用第一个。
几乎就像您在问题中所写的那样,在辅助函数中,另一个重载解决方案可以转换ReadOrWrite()
template <typename ... Args, typename ST>
void ReadOrWrite_helper (ST &, typename std::conditional<
std::is_same<ST, std::ifstream>::value,
std::vector<Args...>,
std::vector<Args...> const>::type vec)
{ Overload(vec); }
添加一对重载的ReadOrWrite()
函数以选择选择Args...
并显式调用助手函数
template <typename ... Ts>
void ReadOrWrite (std::ifstream & is, std::vector<Ts...> & vec)
{ ReadOrWrite_helper<Ts...>(is, vec); }
template <typename ... Ts>
void ReadOrWrite (std::ofstream & is, std::vector<Ts...> const & vec)
{ ReadOrWrite_helper<Ts...>(is, vec); }
[注意,由于Args...
类型是在非推论上下文中进行说明的,因此,我将它们放在ReadOnWrite_helper()
模板参数声明中,before ST
;因此也无需明确显示ST
。