【问题标题】:How to pass binary function to template function C++如何将二进制函数传递给模板函数C++
【发布时间】:2016-12-15 13:40:12
【问题描述】:

我想将标准化的 C++ 二进制函数传递给模板函数,但不知何故我没有让它工作。

以下是我的尝试:

template<template <typename> typename Pred,typename T, typename Iterator>
void iota_stepa(Iterator begin, Iterator end, T startofSequence_, T threadStep)
{
    int currMaxThreads = startofSequence_;
    bool first = true;
    generate(begin, end,  Pred<T>(currMaxThreads, threadStep) );
}

并通过以下方式对其进行测试:

vector<int> tempVect_(10, 0);

iota_stepa<std::plus>(begin(tempVect_),end(tempVect_),1,thread::hardware_concurrency());

不幸的是给了我错误:

Severity    Code    Description Project File    Line    Suppression State
Error   C2440   '<function-style-cast>': cannot convert from 'initializer list' to 'std::plus<int>'
Error   C2672   'generate': no matching overloaded function found   FractalCarpet   
Error   C2780   'void std::generate(_FwdIt,_FwdIt,_Fn0)': expects 3 arguments - 2 provided  FractalCarpet

控制台输出如下所示:

1>  c:\users\mtunca\documents\esd\sps\fractalcarpet\main.cpp(55): note: see reference to function template instantiation 'void iota_stepa<std::plus,int,std::_Vector_iterator<std::_Vector_val<std::_Simple_types<float>>>>(Iterator,Iterator,T,T)' being compiled
1>          with
1>          [
1>              Iterator=std::_Vector_iterator<std::_Vector_val<std::_Simple_types<float>>>,
1>              T=int
1>          ]
1>c:\users\mtunca\documents\esd\sps\fractalcarpet\main.cpp(34): error C2672: 'generate': no matching overloaded function found
1>c:\users\mtunca\documents\esd\sps\fractalcarpet\main.cpp(34): error C2780: 'void std::generate(_FwdIt,_FwdIt,_Fn0)': expects 3 arguments - 2 provided
1>  c:\program files (x86)\microsoft visual studio 14.0\vc\include\algorithm(1532): note: see declaration of 'std::generate'

谁能帮帮我,如何解决这个问题?

【问题讨论】:

  • 输出窗口中的有用信息通常比错误列表中的更多。
  • 如果startofSequencethreadStep 都是整数(intunsigned int),那么T 到底如何解析为浮点数?我无法完全重现它。至于C2780 - 你的std::plus 构造函数看起来很奇怪,你为什么要向它传递参数?
  • 就我个人而言,我只是将它作为iota_stepa 的函数参数,然后给它一个像Func 这样的模板类型。这样你就可以传递其他“函数”,比如 lambdas。
  • 您希望Pred&lt;T&gt;(currMaxThreads, threadStep) 生成什么? generate 需要一个不带参数并在调用时返回值的函数。您将不得不将类似行为的东西传递给它。
  • generate 采用无参数函数,返回“下一个”元素。 std::plus 的实例将两个数字相加。如果您描述了您正在尝试解决的问题,而不是您在尝试解决问题时遇到的问题,您可能会得到更好的帮助。

标签: c++ c++11 templates stl std


【解决方案1】:

std::generate 需要一个生成器,可以称为gen()。 您可以使用 lambda 创建一个,可能是这样的:

template<template <typename> class Pred, typename T, typename Iterator>
void iota_stepa(Iterator begin, Iterator end, T startofSequence_, T threadStep)
{
    bool first = true;
    T current;
    auto gen = [&]() -> T
    {
        if(first) {
            current = startofSequence_;
            first = false;
        } else {
            current = Pred<T>() ( current, threadStep );
        }
        return current;
    };
    generate(begin, end, gen );
}

【讨论】:

  • 这解决了问题。谢谢!我的目的是生成一个像 {128,256,512,...} 这样的全面地图,这样我就可以在 GPU 上使用不同的线程进行性能分析。
【解决方案2】:
Pred<T>(currMaxThreads, threadStep) );

Pred&lt;T&gt; 是一种类型。您需要构造一个实际的可调用对象:

Pred<T>()(currMaxThreads, threadStep) );

但这不能是std::generate 的最后一个参数。后者需要一个没有参数的可调用对象,大概持有一个状态(否则调用 std::fill 就足够了)。目前尚不清楚如何调整任意二元函数来填补这个角色。

【讨论】:

  • Pred&lt;T&gt;()(currMaxThreads, threadStep) ); 不可能是正确的。当generate 需要一个函数对象时,它会返回一个值。
  • 这是一个有根据的猜测。我无法完全重现该错误。请发帖minimal reproducible example
  • @NathanOliver 单独查看,原行有一个非常具体的错误反映在错误信息中,固定行修复了那个具体的错误。固定线路是否适合更大的上下文,我不知道。也许原始代码有不止一个错误
  • 是的,原始代码有不止一个错误。您的解决方案的问题是它用另一个错误消息替换了一个错误消息。不要投反对票,因为如果他们想调用它,您正在展示正确的语法是什么,但不是您真正需要的。他们需要创建一个函数对象,它不接受任何内容并在每次调用时返回一个值。
  • @NathanOliver 我已将此信息添加到答案中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-06-13
  • 2016-06-01
  • 2014-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多