我正在尝试编写一个通用过滤函数,该函数在多维数组(任意等级)中的给定采样坐标处执行线性插值。为此,我需要一个递归函数模板,它遍历数组的所有维度,直到它遇到一个值及其关联的类型。我使用 boost::enable_if 来检测何时停止迭代维度。它工作正常,直到我尝试将返回值/类型“渗透”到最顶层的函数。为此,我尝试使用 C++0x 类型推断,但它似乎与 boost::enable_if 不能很好地混合。
我将问题隔离如下:
template< typename T, std::size_t I >
auto test(const T &t) -> typename boost::enable_if_c< (I == 0), typename T::value_type >::type
{
return t[0];
}
template< typename T, std::size_t I >
auto test(const T &t) -> typename boost::enable_if_c< (I > 0), decltype(test< T, I - 1 >(T())) >::type
{
return test< typename T::value_type, std::size_t(I - 1) >(t[0]);
}
编译器(GCC 4.6)抱怨以下代码:
typedef std::array< std::array< float, 1 >, 1 > myarray;
myarray ma;
std::cout << typeid (test< myarray, 1 >(ma)).name() << std::endl;
错误消息:
error: conversion from 'boost::enable_if_c<true, float>::type' to non-scalar type 'boost::enable_if_c<true, std::array<float, 1u> >::type' requested
看来 decltype 使用 test< 的返回值T,I>即使指示使用 test< T,I-1>。知道为什么会出现这种行为吗?现在,我认为我会把整个事情变成一个函子......
I'm trying to write a generic filtering function that performs linear interpolation at a given sampling coordinate in an multi-dimensional array (arbitrary rank). For this, I need a recursive function template that walks through all dimensions of an array until it hits a value and its associated type. I use boost::enable_if in order to detect when to stop iterating through the dimensions. It works ok until I try to "percolate" the return value/type to the topmost function. For this purpose, I attempted to use C++0x type inference but it doesn't seem to mix well with boost::enable_if.
I isolated the problem down to what follows:
template< typename T, std::size_t I >
auto test(const T &t) -> typename boost::enable_if_c< (I == 0), typename T::value_type >::type
{
return t[0];
}
template< typename T, std::size_t I >
auto test(const T &t) -> typename boost::enable_if_c< (I > 0), decltype(test< T, I - 1 >(T())) >::type
{
return test< typename T::value_type, std::size_t(I - 1) >(t[0]);
}
The compiler (GCC 4.6) complains with the following code:
typedef std::array< std::array< float, 1 >, 1 > myarray;
myarray ma;
std::cout << typeid (test< myarray, 1 >(ma)).name() << std::endl;
Error message:
error: conversion from 'boost::enable_if_c<true, float>::type' to non-scalar type 'boost::enable_if_c<true, std::array<float, 1u> >::type' requested
It seems that decltype uses the return value from test< T, I > even though it is instructed to use that of test< T, I - 1 >. Any idea why this behavior occurs? For now, it think I'll just turn the whole thing into a functor...
发布评论
评论(1)
问题是您将 T() (和 T)传递给了 decltype。这些类型不会向下折叠。如果您将返回表达式与传递给 decltype 的表达式进行比较,就会清楚地看出这一点 - 它们是不一致的。
decltype: test
返回表达式:test< typename T::value_type
当定义这样的前向函数时,用于定义返回类型的 decltype 表达式几乎应该始终与实际返回表达式完全相同。
编辑:我需要补充一点,当实际上您将传递左值时,您不应该传递右值,尤其是传递给模板,因为您很可能会得到不同的结果。
The issue is that you passed a T() (and T) to decltype. The types aren't folding down. This is clearly revealed if you compare the return expression to what you passed to decltype- they're inconsistent.
decltype: test<T
return expression: test< typename T::value_type
When defining forward functions like this, the decltype-expression used to define the return type should nearly always be exactly the same as the actual return expression.
Edit: I need to add that you should not pass rvalues when in reality you will pass lvalues, especially to templates, as you may well end up with different results.