2

我有一个对各种格式的像素进行操作的容器类。有些格式只是将像素存储在内存中,所以容器的引用类型是 Pixel&。其他格式将像素存储在打包字节中。没有什么可以返回引用,所以这种情况下的引用类型是代理类型。我所有的代理类型都有一个名为 value_type 的嵌入式 typedef,它是底层像素的类型。

当我尝试编写对像素进行操作的函子时,我遇到了问题。例如,我希望能够编写如下内容:

std::for_each( container.begin(), container.end(), Incrementer() );

我已经能够让它以两种不同的方式工作,但我不喜欢其中任何一种,所以我想知道这是否可以改进。

第一种方法是:

struct Incrementer {

  template <typename Pixel>
  void operator()( Pixel& p ) {
    p = p + 1;
  } 

  template <typename Proxy>
  void operator()( Proxy p, typename Proxy::value_type* dummy=0 ) {
    p = p + 1;
  }
};

基本思想是我有两个重载,一个用于容器返回对像素的引用的情况,一个用于返回代理的情况。我需要第二个重载的虚拟参数,以便参考案例是明确的。问题是我使用的每个仿函数都需要这两个重载(包括虚拟参数),所以我认为接口相当丑陋。

也许我可以编写一些模板魔术来整理参数类型,但我一直遇到编译器永远不会推断引用参数的问题,所以我需要提供一个带有非常量引用的重载。另一方面,代理是临时的,因此不能通过非常量引用传递。这让我陷入了两个重载。

有什么我想念的吗?

后备解决方案类似于:

  template < typename PixelReference >
  struct Incrementer {

    void operator()( PixelReference p ) {
      p = p + 1;
    }
  };

  std::for_each( container.begin(), container.end(),      
                 Incrementer< pixel_traits<Pixel,Format>::reference >() );

(假设我有一个像素特征类)。现在我必须在创建仿函数时指定引用类型,这通常很麻烦。

有什么办法可以改进这些替代方案中的任何一个吗?我把这个容器写成一个库,所以我试图让编写和使用函子尽可能容易。

谢谢。

4

2 回答 2

2

使用std::for_each()可能会阻碍你。如果你std::transform()改用呢?它甚至支持相同的就地修改:

transform( container.begin(), container.end(), container.begin(), Incrementer() );

然后Incrementer::operator()只需要为 pass-by-value 实现,因为它不再显式地修改像素。当然,您随后需要支持为您的迭代器分配代理值,但也许这并不难。

于 2013-06-03T13:59:45.543 回答
0

我认为有几种方法可以解决您的问题。

1.在您的示例中,两者operator()都是相同的,因此您已经在使用编译时多态性,而您的问题是多重定义operator()

编辑

代码应如下所示:

struct Incrementer {
  template <typename Pixel_or_Proxy>
  void operator()( Pixel_or_Proxy& p ) {
    p = p + 1;
  }
};

2.使用boost enable_if & disable_if并在boost.mpl BOOST_MPL_HAS_XXX_TRAIT_DEFvalue_type的帮助下检查

3.如果你的代理是一个模板,你可以为它创建一个更好的重载:

template<class T>
void operator()(T t) { 
  // normal operation
}

template<class T>
void operator()(Proxy<T> t) {
  // proxy operation
}

编辑

对于选项 2:由于方法的主体是相等的,您只需要编写一个模板方法。typenamesPixelProxy只是对编译器没有任何语义意义的名称,仅对用户而言。编译器只是用给定的类型实例化模板方法。如果您有不同的方法,则需要通过重载选择其中之一。这可以通过 enable_if 和朋友来完成,或者通过额外的调用在类型 traits 的帮助下完成

于 2013-06-03T14:37:10.760 回答