4

我想了解为什么会失败:

template <class T, class U>
T apply(U stuff, std::function<T (U)> function) { return function(stuff); }

(这当然不是真正的代码)。

在 g++-4.8 上,我得到“模板参数 1 无效”。

谢谢 !


编辑:彻底的例子:基本上,我想做的是为MapFunctionandReductionFunction类型强制执行特定的原型。

我想:

  • MapFunction : typeof(*InputIterator) -> T
  • 减少函数:(T,T)-> T

代码:

template <class T, class InputIterator, class ReductionFunction>
T mapReduce_n(InputIterator in, 
    unsigned int size, 
    T baseval, 
    std::function<T (decltype(*InputIterator))> map, 
    ReductionFunction reduce)
{
    T val = baseval;

    #pragma omp parallel
    {
        T map_val = baseval;

        #pragma omp for nowait
        for (auto i = 0U; i < size; ++i)
        {
            map_val = reduce(map_val, map(*(in + i)));
        }

        #pragma omp critical
        val = reduce(val, map_val);
    }

    return val;
}

编辑 2:

我认为那std::function<T (decltype(*InputIterator))> map部分是错误的,应该是: std::function<T (decltype(*in))> map

然而,这失败了:

mismatched types 'std::function<T(decltype (* in))>' and 'double (*)(std::complex<double>)'

我还尝试了迭代器特征:

std::function<T (std::iterator_traits<InputIterator>::value_type)> map

但它失败了:

type/value mismatch at argument 1 in template parameter list for 
'template<class _Signature> class std::function'

error:   expected a type, got '(T)(std::iterator_traits<_II>::value_type)'

第三次编辑:

另一个试验,我想我开始接近了!

std::function<T (typename std::iterator_traits<InputIterator>::value_type)> map

失败:

mismatched types 
'std::function<T (typename std::iterator_traits<_II>::value_type)>' 
and 
'double (*)(std::complex<double>)'

这是我的电话:

MathUtil::mapReduce_n(
   in, // const std::complex<double> * const
   conf.spectrumSize(), // unsigned int
   0.0, 
   MathUtil::CplxToPower, // double CplxToPower(const std::complex<double> val);
   std::plus<double>())
4

1 回答 1

2

如果您提供一个显示问题的极简示例,而不是将问题嵌入到相当大量的代码中,从而使问题更难被发现,我认为您会更快地获得答案。此外,编辑帖子可能相当于减少文本,删除不相关的材料。就我看到的问题而言,您想传递一个std::function<Signature>可以使用迭代器提供的值的对象。您尝试的基本上相当于此(尽管您发布了不相关的代码片段,但您没有发布完整的示例):

template <typename T, typename Iterator>
void f(Iterator it, T value, std::function<T(decltype(*it))> fun);

double fun(std::complex<double>);
int main() {
    std::complex<double> values[1];
    f(values, 0.0, fun);
}

这段代码试图T从第二个和第三个参数中推断出来。但是,它失败了,因为第三个参数不是预期的形式,即它不是std::function<Signature>. 相反,第三个参数的类型是double(*)(std::complex<T double>). 解决方法可能是传递正确类型的参数,这确实与函数模板匹配:

f(值, 0.0, std::function)>(fun));

当然,这不是太漂亮,并且f()比必要的更难使用。更好的解决方案是进行隐式转换,并且不让第三个参数参与模板参数推导。最简单的方法是不T直接提及:

template <typename T>
struct hide_type
{
    typedef T type;
};

template <typename T, typename Iterator>
void f(Iterator it,
       T        ,
       std::function<typename hide_type<T>::type(decltype(*it))>);

使用嵌套在内部的类型hide_type<T>会导致T无法从第三个参数推导出来,相反,如果第三个参数与类型不匹配,则可能会尝试进行隐式转换。最后,您在使用value_type指定参数时遇到了问题。尽管函数的参数并不是真正的问题,您也可以使用value_type,但是您需要使用它typename来表示依赖名称value_type是一种类型:

template <typename T, typename Iterator>
void f(Iterator it,
       T        ,
       std::function<typename hide_type<T>::type(typename std::iterator_traits<Iterator>::value_type>);

签名仍然需要以一种不会导致模板参数推导考虑的方式来制定。

于 2013-08-24T22:23:18.797 回答