Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/149.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在这种情况下,有什么方法可以改进模板参数推断吗?_C++_Templates - Fatal编程技术网

C++ 在这种情况下,有什么方法可以改进模板参数推断吗?

C++ 在这种情况下,有什么方法可以改进模板参数推断吗?,c++,templates,C++,Templates,我有一个容器类,它对各种格式的像素进行操作。有些格式只是将像素存储在内存中,因此容器的引用类型是Pixel&。其他格式以压缩字节存储像素。没有可返回引用的对象,因此这种情况下的引用类型是代理类型。我的所有代理类型都有一个名为value_type的嵌入式typedef,它是底层像素的类型 当我试图编写对像素进行操作的函子时,遇到了一个问题。例如,我希望能够写出如下内容: std::for_each( container.begin(), container.end(), Incrementer()

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

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

std::for_each( container.begin(), container.end(), Incrementer() );
  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 >() );
我已经能够用两种不同的方法来实现这一点,但我不喜欢这两种方法中的任何一种,所以我想知道这是否可以改进

第一种方法是:

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;
  }
};
struct递增器{
模板
void操作符()(像素和p){
p=p+1;
} 
模板
void运算符(){
p=p+1;
}
};
基本思想是我有两个重载,一个用于容器返回像素引用的情况,另一个用于返回代理。我需要第二个重载的伪参数,以便参考情况是明确的。问题是我使用的每个函子都需要这两个重载(包括伪参数),所以我认为接口相当难看

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

有什么我遗漏的吗

后备解决方案类似于:

std::for_each( container.begin(), container.end(), Incrementer() );
  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 >() );
模板
结构增量器{
void操作符(){
p=p+1;
}
};
std::for_each(container.begin()、container.end(),
递增器());
(假设我有一个像素特性类)。现在我必须在创建函子时指定引用类型,这通常很麻烦

我有什么办法可以改进这两种选择中的任何一种吗?我将这个容器作为一个库来编写,所以我试图使编写和使用函子尽可能简单

谢谢

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

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

然后,
Incrementer::operator()
只需要为passby value实现,因为它不再显式地在适当的位置修改像素。当然,您需要支持为迭代器分配代理值,但这可能并不困难。

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

1.在您的示例中,两个
operator()
s是相同的,因此您已经在使用编译时多态性,您的问题是
operator()

编辑:

代码应该如下所示:

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


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

我绝对可以做到。将代理分配给迭代器很好,所以我认为这是一个很好的技术解决方案。我唯一担心的是,我将容器作为一个库来编写,我认为用户希望每个容器都能正常工作,而不会向后过度弯曲以容纳代理。谢谢。是的,方法是一样的。我只是想不出一个同时适用于两者的方法声明,所以我最终实现了两次。关于#2,我的伪论点与enable#if会做什么不一样吗?因为函数对象必须由用户编写,所以我不想让它们暴露在他们可能不熟悉的boost库中。对于#3,它不是一个模板,但我可以编写一个模板包装器,使该语法起作用-如果事情没有实际意义,这将使dummy_arg/enable_。谢谢。两个重载的原因是其中一个(非代理)必须是非常量引用,但代理不能是非常量引用,因为代理是临时的。