【问题标题】:Cannot call generic std::function member from template class无法从模板类调用通用 std::function 成员
【发布时间】:2016-02-10 19:31:45
【问题描述】:

编译以下代码时:

#include <functional>

template <typename functionSignature>
class Class
{        
    std::function<functionSignature> func;
public:
    Class(const std::function<functionSignature>& arg) : func(arg) {}
    void callFunc() { func(); }
};

void f(const int i) {}

int main()
{
    Class<void(const int)> a(std::bind(f, 10));
    a.callFunc();
    return 0;
}

VS 2015 编译器在第六行生成如下错误信息:

error C2064: term does not evaluate to a function taking 0 arguments.

现在,我相信这是因为编译器认为functionSignature 不是函数签名;例如,当我实例化并尝试在std::function&lt;int&gt; 而不是std::function&lt;int()&gt; 上调用operator() 时,也会发生同样的错误。

如何保证模板参数始终是函数签名,以便我可以在std::function 上调用operator()

【问题讨论】:

  • 您能否准确地更新您的代码,您如何调用您的课程以及您如何初始化您的课程?
  • 是的,实际的 MCVE 会有所帮助。只需添加一个玩具main,它会创建一个Class&lt;some stuff here&gt; 的实例,然后在其上执行.callFunc(),并确认它编译并在MSVC 中生成错误。

标签: c++ function class templates c++11


【解决方案1】:

我怀疑你想要这样的东西:

template <typename F>
class Class;

template<typename R, typename... P>
class Class<R(P...)> {
public:
    std::function<R(P...)> func;
    void callFunc(P... p) { func(p...); }
};

通过这种方式使用部分特化,您可以轻松定义所需的类型。
例如,您可以将其用作:

Class<int(double)> c;

当然,我注意到您的类没有构造函数,因此调用 func 不是一个好主意,但定义它并传递适当的函数作为参数非常容易。

它遵循一个完整且有效的示例,我使用operator() 来调用该函数:

#include <functional>

template <typename F>
class Class;

template<typename R, typename... P>
class Class<R(P...)> {
public:
    Class(std::function<R(P...)> f): func{f} { }
    void operator()(P... p) { func(p...); }
private:
    std::function<R(P...)> func;
};

void fn() { }

int main() {
    std::function<void()> f = fn;
    Class<void()> c{f};
    c();
}

【讨论】:

  • +1,这回答了我用谷歌搜索的问题,以及我根据问题标题认为的问题。
【解决方案2】:

你的错误在这里:

Class<void(const int)> a(std::bind(f, 10));

函数Class::callFunc() 调用func()——即没有参数。 std::bind(f, 10) 的结果也是一个不带参数的函数,与类模板的模板参数一致。使用Class&lt;void(const int)&gt;与类模板中的用法和初始化都不一致。

解决方法很简单:将错误行改为

Class<void()> a(std::bind(f, 10));

【讨论】:

  • 好吧,既然OP改变了原来的问题,我的第一个答案仍然有道理,但这一个确实更集中。
  • @skypjack - 在你写下你的答案时,没有太多事情要做。您阅读了 OP 的想法,然后是一些。 +1,根据您的回答,就是这样。
【解决方案3】:

这是你想要做的吗?

http://ideone.com/fork/IZ0Z1A

如果 functionSignature 不是一个函数,std::function 会在你创建 Class 时抛出错误,但你可以添加一个构造函数并在那里抛出一个 static_assert(std::is_function&lt;functionSignature&gt;::value == true," ");如果你想我猜。

#include <functional>
#include <iostream>

template <typename functionSignature>
class Class
{
public:
    std::function<functionSignature> func;
    void callFunc() { func(); }
};

void f()
{
    std::cout << "hello" << std::endl;
}

int main()
{
    Class<decltype(f)> t {f};
    t.callFunc();

    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-27
    • 1970-01-01
    • 2018-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-21
    相关资源
    最近更新 更多