开发者

templated function pointer, is this possible?

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;

The above code basically doesnt compile. I think its syntax error with the following line:

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

What is the correct syntax?

Thanks.

edit: @ James, This is the declaration of a const class member function template. The function takes the following arguments

1) an unsigned int

2) a priority_queue, sorted in an arbitrary manner specified by the cli开发者_运维技巧ent

The function returns a vector of unsigned ints.


Try this:

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;


Why would you need a function pointer as a template argument? std::priority_queue expects a function class (like less<> that has an operator() defined), not a C-style function pointer.

The following code will not work, even without a template argument:

bool(*fn)(const unsigned&, const unsigned&) = 0;

std::priority_queue<std::pair<unsigned, unsigned>,
    std::vector<std::pair<unsigned, unsigned>>, fn> q;

What you need to do, is what Rob has suggested:

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;

Where T is the Comparer type.


Is Traverse a stand alone function ? If yes then you should remove const in the very end. It compiles with that change. Also change (*T) to simply (*).

If it's a member of a class then also it should compile.


Derived from here.

priority_queue accepts a function pointer for the compare argument, but you'd have to pass the function pointer to the constructor, not the template. The template would just accept the type of the function pointer.

The easiest way to implement this would be to use a functor (function object, predicate class or however you name it).

From that functor, you could also call the function pointer, provided it is known globally at compile time. But I assume it isn't so you might have to go the 'pass function pointer in constructor' route after all.

If the function address is known at compile time:

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;

If it isn't:

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);
}

In short, the template is pretty much useless here, because a function is not a type, and the type of the compare function is 100% predetermined (it's MyQueue). The compiler wouldn't have any information to infer a specific type from the arguments passed to Traverse().

If you don't actually need to change the comparison function dynamically during runtime, the other answers here are the way to go. Just pass T as the third template argument to your priority_queue.


Your edit helps some. There's still the problem that std::priority_queue isn't a type, so you can't declare a function using it. But since you've already got a template, the simplest solution would be:

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

Trying to restrict Q to a set of instantiations of priority_queue can doubtlessly be done, but it will be tricky; you'll probably need some sort of template wrapper class with template template parameters and partial specialization.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜