Beginner template compile error - Having trouble passing function as arg
Most of my classes have lists as private data members. As such, most of them also have adder/开发者_运维知识库remover public members. I noticed I was writing basically the same thing for each of the adders, so I thought I'd turn it into a template.
Here's what I've got:
template <class N, class I>
void add(N element, std::list<N> & container, I (*f)(void),
std::string successmsg, std::string exceptmsg) {
typename std::list<N>::iterator it;
it = find(container.begin(), container.end(), element);
try {
if(it != container.end())
throw DuplicateElement<I>(element->(*f));
}
catch (DuplicateElement<I>&){
std::cout << exceptmsg;
pause(PAUSE_MESSAGE);
return;
}
container.push_back(element);
std::cout << successmsg;
}
Let me just explain this one, its parameters (in order) are the element to add, the container which the element shall be added to, a function present on the element class that returns its unique ID (a code, a license plate, whatever), a success message and an exception message.
Sample usage:
void Aeroporto::addCompanhia(CompanhiaAerea* companhia) {
std::string success = "Companhia aérea adicionada com sucesso!";
std::string except = "Companhia aérea já existente!";
add(companhia, companhias, getSigla, success, except);
// std::list<CompanhiaAerea*>::iterator it;
//
// it = find(companhias.begin(), companhias.end(), companhia);
// try{
// if(it != companhias.end())
// throw DuplicateElement<std::string>(companhia->getSigla());
// }
// catch (DuplicateElement<std::string>&){
// std::cout << "Companhia aérea já existente!";
// pause(PAUSE_MESSAGE);
// return;
// }
//
// companhias.push_back(companhia);
// std::cout << "Companhia aérea adicionada com sucesso!";
}
When I try to compile this, I get the following:
..\src\/headers/template.h: In function 'void add(N, std::list<N>&, I (*)(), std::string, std::string)':
..\src\/headers/template.h:23:29: error: expected primary-expression before '(' token
..\src\/headers/template.h:23:39: error: expected unqualified-id before '(' token
..\src\aeroporto.cpp: In member function 'void Aeroporto::addCompanhia(CompanhiaAerea*)':
..\src\aeroporto.cpp:76:54: error: no matching function for call to 'add(CompanhiaAerea*&, std::list<CompanhiaAerea*>&, <unresolved overloaded function type>, std::string&, std::string&)'
I require your assistance since it's not particularly easy to google for this kind of stuff.
Thank you for your time!
Because you want to use a method, you have to use a pointer-to-member-function:
template <class N, class I>
void add(N* element, std::list<N*>& container, I (N::*f)() const,
std::string successmsg, std::string exceptmsg) {
typename std::list<N*>::iterator it;
it = find(container.begin(), container.end(), element);
try {
if(it != container.end())
throw DuplicateElement<I>((element->*f)());
//...
//...
add(companhia, companhias, &CompanhiaAerea::getSigla, success, except);
//...
Note how I had to change the way N is used, in order to get the right type for f.
You do not want to pass a function pointer, but a member function pointer. They are quite different in C++ (basically the implicit this
argument). This is a simple test case on how free functions, static member functions and non-static member functions can be passed around. You will have to complete it with the template part:
struct test {
void foo() { std::cout << "test::foo" << std::endl; }
static void bar() { std::cout << "test::bar" << std::endl; }
};
void foo() { std::cout << "foo" << std::endl; }
void call_function( void (*f)() )
{
f();
}
void call_member( test & t, void (test::*f)() )
{
t.*f();
(&t)->*f();
}
int main()
{
test t;
call_function( &foo ); // free function
call_function( &test::bar ); // equivalent for static member function
call_member( t, &test::foo ); // but not for member function
}
精彩评论