Ошибка компиляции шаблона для начинающих - возникла проблема при передаче функции в качестве аргумента - PullRequest
1 голос
/ 30 октября 2010

Большинство моих классов имеют списки в качестве личных данных.Также, у большинства из них также есть общественные участники сумматора / удаления.Я заметил, что пишу в основном одно и то же для каждого из сумматоров, поэтому я решил превратить его в шаблон.

Вот что я получил:

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

Позвольтея просто объясню это, его параметры (по порядку) - это элемент для добавления, контейнер, к которому должен быть добавлен элемент, функция, присутствующая в классе элемента, которая возвращает свой уникальный идентификатор (код, номерной знак, что угодно), сообщение об успехе и сообщение об исключении.

Пример использования:

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!";

}

Когда я пытаюсь скомпилировать это, я получаю следующее:

..\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&)'

Мне требуетсяВаша помощь, потому что не очень легко гуглить для такого рода вещей.

Спасибо за ваше время!

Ответы [ 2 ]

3 голосов
/ 30 октября 2010

Поскольку вы хотите использовать метод, вы должны использовать функцию указателя на член:

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);
//...

Обратите внимание, как мне пришлось изменить способ использования N, чтобы получить правильный тип для f.

2 голосов
/ 30 октября 2010

Вы не хотите передавать указатель на функцию, но указатель на функцию-член . Они совершенно разные в C ++ (в основном неявный аргумент this). Это простой тестовый пример того, как можно передавать свободные функции, статические функции-члены и нестатические функции-члены. Вам нужно будет заполнить его частью шаблона:

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
}
...