C++ 将带有模板参数的函数作为参数传递,函数指针与std::function

C++ 将带有模板参数的函数作为参数传递,函数指针与std::function,c++,c++11,templates,C++,C++11,Templates,所以我有一个泛型类,它有两个函数,以函数为参数。一个接受函数指针,一个接受std::函数。两者都有一个模板参数 #include <functional> #include <memory> namespace { void example(const std::shared_ptr<const int>&) {} } class Generic { public: Generic() {} virtual ~Generic

所以我有一个泛型类,它有两个函数,以函数为参数。一个接受函数指针,一个接受std::函数。两者都有一个模板参数

#include <functional>
#include <memory>

namespace {
    void example(const std::shared_ptr<const int>&) {}
}

class Generic {
public:
    Generic() {}
    virtual ~Generic() {}
    template <typename Targ>
    void doWork(std::function<void(const std::shared_ptr<const Targ>&)> arg) {}

    template <typename Targ>
    void doWork2(void(*function)(const std::shared_ptr<const Targ>&)) {}
};

class Special : public Generic {
public:
    Special() {
        //doWork(&example);   // Fail!
        doWork<int>(&example);  // OK!
        std::function<void(const std::shared_ptr<const int>&)> func = &example;
        doWork(func); // OK!
        doWork2(&example);  // OK!
    }
};

int main(int argc, char** argv) {
    Special special;
    return 0;
}
#包括
#包括
名称空间{
void示例(const std::shared_ptr&){}
}
类泛型{
公众:
泛型(){}
虚拟~Generic(){}
模板
void doWork(std::function arg){}
模板
void doWork2(void(*函数)(const std::shared_ptr&){
};
特殊类:公共泛型{
公众:
特别(){
//doWork(示例);//失败!
道工(示例);//好的!
std::function func=&示例;
doWork(func);//好的!
doWork2(&示例);//好的!
}
};
int main(int argc,字符**argv){
特别的;
返回0;
}
它使用函数指针编译,但使用std::函数则不编译。为什么模板推导在这里失败

叮当声报道:

example.cpp:27:9: error: no matching member function for call to 'doWork'
        doWork(&example);
        ^~~~~~
example.cpp:14:10: note: candidate template ignored: could not match 'function<void (const shared_ptr<const type-parameter-0-0> &)>' against 'void (*)(const std::shared_ptr<const int> &)'
    void doWork(std::function<void(const std::shared_ptr<const Targ>&)> arg) {
         ^
1 error generated.
example.cpp:27:9:错误:调用“doWork”时没有匹配的成员函数
道具(示例);
^~~~~~
示例.cpp:14:10:注意:已忽略候选模板:无法将“函数”与“void(*)(const std::shared_ptr&)”匹配
void doWork(std::function arg){
^
生成1个错误。

发生这种情况是因为构造函数无法推断其类的类型。如果我的措辞听起来很奇怪,也许这个示例会有所帮助:

template <class T>
class Example {
    Example(const T&) { /*...*/  }
};
模板
课例{
示例(常量T&){/*…*/}
};
如果我有一个函数模板,比如
template void f(const-Example&)
,我就不能只做
f(10)
。这就是你的代码的本质。
std::function
不能根据你传递给它的(非显式)构造函数的内容来知道它的模板参数


注意:顺便说一句,这是在C++17中出现的。

发生这种情况是因为构造函数无法推断其类的类型。如果我的措辞听起来很奇怪,也许这个例子会有所帮助:

template <class T>
class Example {
    Example(const T&) { /*...*/  }
};
模板
课例{
示例(常量T&){/*…*/}
};
如果我有一个函数模板,比如
template void f(const-Example&)
,我就不能只做
f(10)
。这就是你的代码的本质。
std::function
不能根据你传递给它的(非显式)构造函数的内容来知道它的模板参数


注意:顺便说一句,这是在C++17中使用的。

模板参数推导不是这样工作的


模板参数推断是一种模式匹配。
example
是某种类型的
target
std::function
对象吗

不可转换为,但实际上已经是该类型的对象了

不,不是

但是,它已经是一个函数指针(使用隐式衰减规则)


有一个C++17功能涉及从构造函数类型推断模板参数;
std::function
可能会也可能不会在C++17或C++20出现这种情况时被检测到从函数指针学习自己的类型。可以肯定的是,我缺乏C++17方面的专业知识。

模板参数推断不是这样工作的。


模板参数推断是一种模式匹配。
example
是某种类型的
target
std::function
对象吗

不可转换为,但实际上已经是该类型的对象了

不,不是

但是,它已经是一个函数指针(使用隐式衰减规则)


有一个C++17功能涉及从构造函数类型推断模板参数;
std::function
可能会也可能不会在C++17或C++20出现这种情况时被检测到从函数指针学习自己的类型。我确实缺乏C++17方面的专业知识。

示例
不是
std::function
,而且可能有几个
std::function
可以从这个函数构造出来。@Jarod42但是
&example
是一个函数指针,我可以把一个函数指针作为
std::function
传递,不?
示例
不是
std::function
,可能有几个
std::function
可以构造出来这个函数。@Jarod42但是
&example
是一个函数指针,我可以将函数指针作为
std::function
传递,不是吗?我肯定缺乏C++17方面的专业知识。我想和你一样缺乏专业知识。:-)我肯定缺乏C++17方面的专业知识。我想和你一样缺乏专业知识。:-)