2

我有一个全局函数,可以将一个对象(或 type Source)的相关位复制到另一个( type 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 );
    }
};

现在的问题是成员函数必须复制到几十个类中。这是一个可以容忍的复制和粘贴编程案例吗?我考虑过放入partialCopy一个头文件partialCopy.h并使用预处理器包含将其“注入”到每个类中,如下所示:

struct Foo
{
    #include "partialCopy.h"
};


Foo f;
Bar b;
f.partialCopy( b );

虽然这是可行的,但我从未在任何地方见过它,也不知道它是否不可接受。

我已经尝试将partialCopy成员函数放在一个公共基类中并继承它,但这不起作用,因为this关键字将引用基类而不是派生类。

有更好的选择吗?请指教。

编辑

John 的建议(在一个已被删除的线程中)我static_cast对 CRTP 基类中的派生类执行一个很好的工作。@John 请发布这个答案,我会这样标记它。

4

5 回答 5

5

我将其发布为答案,因为在我看来这是合适的。不过,Henrik 首先发表了评论。(然而,这也是我的第一个想法:))

常量引用

使用const&(const-reference) 作为源参数。这样就很容易与目标区分开来。

额外的好处是它将验证并确保您的部分复制函数的 const 正确性。

右值引用

您可能还考虑为Source&&. 如果有一些直接复制的缓冲区,您的函数可能会使用它。

于 2013-02-12T12:17:16.037 回答
3

我建议为此重载流运算符。

例如

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&。

所以你可以简单地写

Foo f;
Bar b;
f >> b;

更清楚源对象和目标对象是什么。

于 2013-02-12T12:17:15.053 回答
1

我对这个答案有点晚了,但我认为您可能对使用CRTP作为复制粘贴编程的干净替代方案的解决方案感兴趣:

现在的问题是成员函数必须复制到几十个类中。这是一个可以容忍的复制和粘贴编程案例吗?我考虑将 partialCopy 放在头文件 partialCopy.h 中,并使用预处理器 include 将其“注入”到每个类中 [...]。

不要复制或#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
{
// ...
};
于 2013-02-15T11:48:42.893 回答
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 像一种引用一样工作,并且 from 和 to 像工厂函数一样工作,以便于使用。你也可以尝试实现类似的东西。

partial_copy.from(Source).to(Target);
partial_copy(Source)->_(Target);

但通常这是很多写作。只需将 partial_copy 放在其自己的命名空间中以防止名称冲突,让用户自己进行自定义重载,并使用 const& 来指示源和目标是什么。

于 2013-02-12T12:40:06.627 回答
0

最干净的方法可能就是将其partialCopy作为免费功能保留并以这种方式使用。这并没有本质上的错误,例如标准库<algorithm>头文件中的所有函数都是将与对象一起使用的自由函数。

foo.partialCopy(bar)哪个是源哪个是目的地也不是很清楚。partialCopy复制from还是tobar_ 通常,在这种情况下查看文档/函数声明很有用。如果您对参数有明确的名称并const在适当时进行命名,那么应该非常清楚对象被复制的方式。

于 2013-02-12T12:33:04.327 回答