在这种情况下,有什么方法可以改进模板参数推导吗
Is there any way to improve template argument deduction in this case?
我有一个容器类,可以对各种格式的像素进行操作。有些格式只是将像素存储在内存中,因此容器的引用类型是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 >() );
(假设我有一个像素的特征类(。现在,我必须在创建函子时指定引用类型,这通常很麻烦。
我有什么办法可以改进这两种选择吗?我把这个容器作为一个库来编写,所以我试图让编写和使用函子尽可能简单。
谢谢。
使用std::for_each()
可能会阻碍您。如果您使用std::transform()
呢?它甚至支持相同的就地修改:
transform( container.begin(), container.end(), container.begin(), Incrementer() );
那么Incrementer::operator()
只需要为传递值实现,因为它将不再显式地修改原地的像素。当然,您需要支持为迭代器分配代理值,但这可能并不那么困难。
我认为有几种方法可以解决您的问题。
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_DEF 的帮助下检查value_type
3.如果你的代理是一个模板,你可以为它创建一个更好的过载:
template<class T>
void operator()(T t) {
// normal operation
}
template<class T>
void operator()(Proxy<T> t) {
// proxy operation
}
编辑:
对于选项2:由于方法的主体是相等的,您只需要编写一个模板方法。类型名Pixel
和Proxy
只是对编译器没有任何语义意义的名称,只是对用户。编译器只是用给定的类型实例化模板方法。如果你有不同的方法,你需要通过重载来选择其中一个。这可以通过enable_if和朋友来完成,也可以在类型特征的帮助下通过额外的调用来完成。
- 我是c ++的新手,你能解释一下在这种情况下的指针吗
- 在这种情况下,java对象是否可以调用本机函数
- 在这种情况下显式调用时,std::cout 如何更改析构函数的行为?
- 在这种情况下,我真的复制了字节还是复制了字符?
- 如何在不知道C++中有多少可选参数的情况下在循环中使用va_arg?
- 为什么在这种情况下,bool 类型的输出等于 0?
- 如何在不强制转换每个参数的情况下删除初始值设定项列表中从 int 到 char 的缩小转换?
- 如何在不传递命令行参数的情况下在 c++ 中设置环境变量
- C++有什么方法可以在既不调用函数模板也不提供其模板参数的情况下引用函数模板?
- 是否可以在不填充自己的参数的情况下将模板函数作为参数传递?
- 在这种情况下,如何传递成员函数而不是函数?
- 为什么在这种情况下递增阵列名称有效?
- 在这种情况下我应该使用哪种设计模式
- 为什么在这种情况下我需要 .template
- 在这种情况下,使用 string_view 是否会导致不必要的字符串复制?
- 模板模板参数 - 在这种情况下为什么需要它们
- 为什么在这种情况下不考虑依赖于参数的查找?
- 为什么在这种情况下c++模板参数推导失败
- 在这种情况下,有什么方法可以改进模板参数推导吗
- 在这种情况下模板参数推导是如何工作的