I wasn't sure what to search for, so I'll try to explain as开发者_JAVA技巧 best as possible. In the STL, std::set
is defined as
template <class Key, class Compare, class Allocator> class set;
From http://cplusplus.com:
Compare: Comparison class: A class that takes two arguments of the same type as the container elements and returns a bool. The expression comp(a,b), where comp is an object of this comparison class and a and b are elements of the container [...]. This can either be a class implementing a function call operator or a pointer to a function [...].
I am talking about the Compare
template parameter.
So if I were to write a template class, that has a template parameter which is a class implementing a function call operator, I'd write
template <class T, class Combine>
class MyClass
{
public:
Combine func;
MyClass()
{
func = Combine();
}
T do_it(T a, T b)
{
return func(a, b);
}
};
class IntCombine
{
public:
int operator () (int a, int b)
{
return a + b;
}
};
//...
MyClass<int, IntCombine> ob;
ob.do_it(4, 5);
Or, if I were to write it so the second template parameter is a function:
template <class T, T Combine(T, T)>
class MyClass
{
public:
Combine func;
MyClass()
{
func = Combine;
}
T do_it(T a, T b)
{
return func(a, b);
}
};
int IntCombine(int a, int b)
{
return a + b;
}
//...
MyClass<int, IntCombine> ob;
ob.do_it(4, 5);
However, in the STL you can use the set class either way. How is this realised? The above code works only if the second template parameter in my definition of ob
is either a class implementing operator ()
or a function, respectively, but I cannot write MyClass
so that both will work.
My examples may look fairly useless. Basically I want to write a container that can combine elements, and that is as generic as the STL containers.
The above code works only if the second template parameter in my definition of ob is either a class implementing operator () or a function, respectively, but I cannot write MyClass so that both will work.
Yes you can:
template <typename F>
struct foo {
F f;
void call() {
f();
}
};
void function() {
std::cout << "function called" << std::endl;
}
int main() {
foo<void(*)()> a = { function };
a.call();
}
This is exactly following the example of the std::set
constructor. The important point is that if you’re using a function pointer, the template parameter is not that function pointer, it’s the type of the function pointer (here void (*)()
). You need to store the actual function pointer separately.
精彩评论