我有一个全局函数可以将一个对象(或类型Source
)的相关位复制到另一个对象(类型为Target
),如下所示:
template<typename Source , typename Target>
void partialCopy( Source& source , Target& target )
{
// perform copy
}
我发现全局函数的问题在于,与成员函数不同,编码两个参数中的哪一个是源,哪个是目标时,不能立即清楚。因此,我希望在每个类中都有一个成员函数partialCopy()
,如下所示:
struct Foo
{
template<typename T>
void partialCopy( T& target )
{
::partialCopy( *this , target );
}
};
现在的问题是必须将成员函数复制到几十个类中。这是copy and paste programming的可容忍的案例吗?我已经考虑将partialCopy
放在头文件partialCopy.h
中并使用预处理器include将它'注入'到每个类中,如下所示:
struct Foo
{
#include "partialCopy.h"
};
Foo f;
Bar b;
f.partialCopy( b );
虽然这有效,但我从未在任何地方看到它,也不知道它是否不可接受。
我已经尝试将partialCopy
成员函数放在公共基类中并继承它但这不起作用,因为this
关键字将引用基类而不是派生类类。
还有更好的选择吗?请指教。
修改
John的建议(在一个被删除的线程中)我对CRTP基类中的派生类执行static_cast
的工作很好。 @John请发一个答案,我会将其标记为。
答案 0 :(得分:5)
我发布这个作为答案,因为在我看来这是合适的。不过Henrik首先评论道。 (但是,这也是我的第一个想法:))
对源参数使用const&
(const-reference)。这样,它很容易与目标区分开来。
额外的好处是它将验证并确保部分复制功能的正确性。
您可能还会考虑为Source&&
重载它。如果有一些直接复制的缓冲区,你的函数可能会使用它。
答案 1 :(得分:3)
我建议为此重载流操作符。
E.g。
template<typename Source , typename Target>
void partialCopy(Source& source, Target& target)
{
// perform copy
}
有效地成为:
template<typename Source , typename Target>
void operator>>(const Source& source, Target& target)
{
// perform copy
}
(另请注意,为了清楚起见,Source参数现在是一个const&amp ;.
所以你可以简单地写一下
Foo f;
Bar b;
f >> b;
使源和目标对象更加清晰。
答案 2 :(得分:1)
我对此答案有点迟了,但我认为您可能对使用CRTP作为复制粘贴编程的干净替代方案的解决方案感兴趣:
现在的问题是必须将成员函数复制到几十个类中。这是一个可以容忍的复制和粘贴编程案例吗?我考虑过将partialCopy放在头文件partialCopy.h中,并使用预处理器包含来注入&#39;它进入每个班级[...]。
请考虑以下内容,而不是复制或#include代码:
// common code:
<template typename T>
class PartialCopyImplementer
{
public:
template<typename D>
void partialCopy(D& destination)
{
// ::partialCopy( *this , target );
}
};
// concrete implementations
class Foo1 : public PartialCopyImplementer<Foo1> // CRTP implementation
{
// ...
};
// concrete implementations
class Foo2 : public PartialCopyImplementer<Foo2> // CRTP ensures Foo1 and Foo2
// do not have a common base
{
// ...
};
答案 3 :(得分:0)
最干净的方法可能就是将partialCopy
作为自由函数保留,以此方式使用它。这没有什么本质上的错误,例如标准库<algorithm>
header中的所有函数都是将与对象一起使用的自由函数。
foo.partialCopy(bar)
哪个是来源,哪个是目的地也不是很清楚。 partialCopy
是否将从或复制到 bar
?通常,在这种情况下查看文档/函数声明很有用。如果您有适当的参数名称并在适当时使它们const
,那么应该非常清楚对象被复制的方式。
答案 4 :(得分:0)
怎么样:
template<class T>
struct from_impl
{
T const& from;
from_impl(T const& f)
: from(f)
{}
};
template<class T>
from_impl<T> from(T const& f) {
return from_impl(f);
}
template<class T>
struct to_impl
{
T& to;
to_impl(T& t)
: to(t)
{}
};
template<class T>
to_impl<T> to(T& t) {
return to_impl(t);
}
template<class T>
void to(T const&); // prevent using with non-const values
template<class Source,class Target>
void partial_copy(from_impl<Source> source, to_impl<Target> target)
{
// use source.from and target.to to perform copy
}
// usage:
T1 object1;
T2 object2;
partial_copy(from(object1),to(object2));
这清楚地说明了你想做什么。 from_impl和to_impl的工作方式类似于一种引用,并且可以作为工厂函数使用,以便于使用。你也可以尝试实现类似的东西。
partial_copy.from(Source).to(Target);
partial_copy(Source)->_(Target);
但是,正常情况下这是很多写作。只需将partial_copy放在自己的命名空间中以防止名称冲突,让用户自己重载以进行自定义并使用const&amp; amp;用于表示源和目的地是什么。