模板化函数指针,这是可能的吗?

templated function pointer, is this possible?

本文关键字:函数 指针      更新时间:2023-10-16
template<typename T>
std::vector<unsigned> 
Traverse
(
unsigned    start_node, 
std::priority_queue
< 
    std::pair< unsigned, unsigned >, 
    std::vector< std::pair<unsigned, unsigned> >, 
    bool(*T)(const unsigned&, const unsigned&) 
> &pQueue
) const;

上面的代码基本上不能编译。我认为这是下面一行的语法错误:

    bool(*T)(const unsigned&, const unsigned&) 

正确的语法是什么?

谢谢。

编辑:@詹姆斯,这是const类成员函数模板的声明。该函数接受以下参数

1) unsigned int

2)一个优先级队列,按客户端指定的任意方式排序

函数返回一个无符号整型的vector对象

试试这个:

template<typename T>
std::vector<unsigned> 
Traverse
(
unsigned    start_node, 
std::priority_queue
< 
    std::pair< unsigned, unsigned >, 
    std::vector< std::pair<unsigned, unsigned> >, 
    T
> &pQueue
) const;

为什么需要一个函数指针作为模板参数?std::priority_queue期望一个函数类(比如定义了operator()的less<>),而不是c风格的函数指针。

即使没有模板参数,下面的代码也不能工作:

bool(*fn)(const unsigned&, const unsigned&) = 0;
std::priority_queue<std::pair<unsigned, unsigned>,
    std::vector<std::pair<unsigned, unsigned>>, fn> q;

你需要做的,就是Rob的建议:

template<typename T>
std::vector<unsigned> 
Traverse
(
unsigned    start_node, 
std::priority_queue
< 
    std::pair< unsigned, unsigned >, 
    std::vector< std::pair<unsigned, unsigned> >, 
    T
> &pQueue
) const;

T为比较器类型

Traverse是一个独立的函数吗?如果是,那么你应该在最后移除const。它会根据这个变化进行编译。也把(*T)改成简单的(*)

如果它是类的成员,那么它也应该编译

从这里派生。

priority_queue接受一个函数指针作为比较参数,但是必须将函数指针传递给构造函数,而不是模板。模板只接受函数指针的类型。

实现这一点最简单的方法是使用一个函子(函数对象、谓词类或随便你怎么称呼它)。

如果在编译时全局知道该函数指针,则还可以从该函函数调用该函数指针。但我认为它不是,所以你可能不得不去'传递函数指针在构造函数'路线毕竟。

如果函数地址在编译时已知:

typedef bool (*MyFuncPtr)(const unsigned&, const unsigned&);
MyFuncPtr globalPtr = myCompareFunction;
struct MyCompare {
    bool operator()(const unsigned &a, const unsigned &b) const {
        return globalPtr(a, b);
    }
};
std::vector<unsigned> 
Traverse
(
unsigned    start_node, 
std::priority_queue
< 
    std::pair< unsigned, unsigned >, 
    std::vector< std::pair<unsigned, unsigned> >, 
    MyCompare 
> &pQueue
) const;

如果不是:

typedef bool (*MyFuncPtr)(const unsigned&, const unsigned&);
typedef std::priority_queue
< 
    std::pair< unsigned, unsigned >, 
    std::vector< std::pair<unsigned, unsigned> >, 
    MyFuncPtr 
> MyQueue;
std::vector<unsigned> 
Traverse
(
unsigned    start_node, 
MyQueue     &pQueue
) const;
int main() {
    MyQueue queue(myCompareFunction);
    Traverse(..., queue);
}

简而言之,模板在这里几乎毫无用处,因为函数不是类型,而比较函数的类型是100%预先确定的(它是MyQueue)。编译器没有任何信息可以从传递给Traverse()的参数中推断出特定的类型。

如果您实际上不需要在运行时动态地更改比较函数,那么这里的其他答案是可行的。只需将T作为第三个模板参数传递给priority_queue。

你的编辑有帮助。还有一个问题std::priority_queue不是类型,所以不能声明一个使用它的函数。但既然你已经有了模板,最简单的解决方案是:

template<typename T, typename Q>
std::vector<unsigned>
Travers( unsigned start_node, Q& pQueue ) const;

试图限制Q的实例化集priority_queue毫无疑问是可以做到的,但这将是棘手的;您可能需要某种模板包装类模板模板参数和局部专门化