使用模板化类型的模板中的函数原型

时间:2013-08-22 06:07:28

标签: c++ templates c++11 functional-programming std

我想理解为什么会失败:

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

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

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

谢谢!


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

我想:

  • MapFunction:typeof(* InputIterator) - &gt; Ť
  • 还原功能:(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>())

1 个答案:

答案 0 :(得分: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(values,0.0,std :: function)&gt;(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>);

签名仍然需要以不会导致模板参数扣除的方式制定。