要想更好地理解问题标题,请考虑以下代码:
template <typename T>
void write(const T& /*data*/)
{
// use data as const
}
template <typename T>
void read(T& /*data*/)
{
// modify data
}
struct S {
int a;
int b;
// a lot of primitive types here
};
void output(const S& s)
{
write(s.a);
write(s.b);
// ...
}
void input(S& s)
{
read(s.a);
read(s.b);
// ...
}
int main()
{
S s;
input(s);
output(s);
}
我有write
和read
函数,可以处理原始数据,例如int
,double
等。我有几种结构类型,例如S
,其中包含很多原始数据成员的类型,我需要通过相应的函数input
和output
输入和输出此类类型(不同类型有很多重载)。如您所见,output
和input
函数的内容基本相同,只是内部函数和类型常量性不同。我想做一些通用的(模板)函数use
,以消除input
/ output
函数中的重复代码。
我认为模板签名如下(但我可能会错过一些东西):
template <typename F, typename T>
void use(T& t) { ... }
所以我可以像这样从use
/ input
调用output
函数:
use<write, S>(s); // in output function
use<read, S>(s); // in input fuction
如何归档这种(或类似的)行为以消除重复的代码?我正在使用C ++ 14。
答案 0 :(得分:1)
template <typename S, typename F>
void use(S&& s, F&& f)
{
f(s.a);
f(s.b);
f(s.c);
}
用法:
use(s, [](const auto& x){ write(x); });
use(s, [](auto& x) { read(x); });
如果您需要多种类型:
template <typename S, typename Target>
using EnableFor = std::enable_if_t<std::is_same_v<std::decay_t<S>, Target>>;
template <typename S, typename F>
auto use(S&& s, F&& f) -> EnableFor<S, S0>
{
f(s.a);
f(s.b);
f(s.c);
}
template <typename S, typename F>
auto use(S&& s, F&& f) -> EnableFor<S, S1>
{
f(s.d);
f(s.e);
f(s.f);
}
用法:
int main()
{
S0 s0;
use(s0, [](const auto& x){ write(x); });
use(s0, [](auto& x) { read(x); });
S1 s1;
use(s1, [](const auto& x){ write(x); });
use(s1, [](auto& x) { read(x); });
}
答案 1 :(得分:0)
您可以定义所使用模板的接口:
template<class M, class S>
void use(S &&s) {
M::method(s.a);
M::method(s.b);
};
然后实施它:
template <typename T>
void write(const T& /*data*/)
{
// use data as const
}
struct writer {
template <typename T>
static void method(const T& t)
{
write(t);
}
};
现在您可以使用它:
use<writer>(s);
对于read
,它是相同的:
struct reader {
template <typename T>
static void method(T& t)
{
read(t);
}
};
use<reader>(s);
答案 2 :(得分:0)
我相信我了解您想要什么,但这是不可能的。当前,尚无办法在所有类的C ++通用流中实现。人们将需要访问诸如类具有的字段数,它们的相对地址以及编译时间类型之类的信息。
当前,他们致力于将其添加到C ++已有多年,请寻求Reflection TS。据我所知,它不会为C ++ 20做好准备。
但是,您可以组织代码,以使每种读/写方法都易于实现。例如:
class A : public B, public C
{
private:
vector<int> m_v;
int m_x;
};
然后将实现写入为
template<>
void write(const A& a)
{
write((const B&)a);
write((const C&)a);
write(a.m_v);
write(a.m_x);
}
对于诸如std::vector<T>
之类的常见数据结构,则通过write<T>
实现写入。这需要时间,但是使其技术化并使用重定向可以节省大量代码和时间。
(您需要将write
设为朋友功能或成员功能,以使其可以访问私人成员)