Указатель на функцию-член в C ++ for_each - PullRequest
5 голосов
/ 19 февраля 2011

Я разрабатываю небольшую виртуальную машину на C ++ для школьного проекта, которая должна работать как команда dc и состоит из элемента Input Output, Chipset, Cpu и Ram. В настоящее время я работаю над набором микросхем, в котором я реализовал небольшой класс синтаксического анализа, чтобы иметь возможность получить некоторые инструкции Asm из стандартного ввода или файла, а затем передать эти инструкции процессору.

Проблема в том, что мои инструкции отсортированы в std :: list, и я хотел бы иметь возможность выдвигать их по каждой инструкции foreach. Для этого мне нужно иметь возможность вызывать мою функцию-член "push_instruction" в качестве указателя на функцию F of_each; и я не смог найти трюк для этого ...

Есть идеи? вот мой код:

/*
** Function which will supervise
** the lexing and parsing of the input (whether it's std_input or a file descriptor)
** the memory pushing of operands and operators
** and will command the execution of instructions to the Cpu
*/
void                    Chipset::startExecution()
{
    /*
    ** My parsing 
    ** Instructions
    **
    */

    for_each(this->_instructList.begin(), this->_instructList.end(), this->pushInstruction);
}


void                    Chipset::pushInstruction(instructionList* instruction)
{
    if (instruction->opCode == PUSH)
      this->_processor->pushOperand(instruction->value, Memory::OPERAND, Memory::BACK);
    else if (instruction->opCode == ASSERT)
      this->_processor->pushOperand(instruction->value, Memory::ASSERT, Memory::BACK);
    else
      this->_processor->pushOperation(instruction->opCode);
}

Ответы [ 4 ]

11 голосов
/ 19 февраля 2011
std::for_each(
    _instructList.begin(), 
    _instructList.end(), 
    std::bind1st(std::mem_fun(&Chipset::pushInstruction), this));
3 голосов
/ 19 февраля 2011

Когда вы не можете вспомнить синтаксис для функций std::bind, иногда проще написать функтор, который просто перенаправляет функцию-член:

struct PushInstruction {
  PushInstruction(Chipset& self) : self(self) {} 

  void operator()(instructionList* instruction) {
    self.pushInstruction(instruction);
  }    

  Chipset& self;    
};

std::for_each(_instructList.begin(), _instructList.end(), PushInstruction(*this));

Немного объяснений:

Я определяю класс, который в своем конструкторе принимает объект, который мы хотим вызвать pushInstruction, и в котором хранится ссылка на объект.

Затем я определяю operator(), который берет инструкцию, которую вы хотите нажать, и вызывает pushInstruction.

В цикле for_each я просто передаю this своему конструктору, создавая экземпляр функтора, который передается в for_each, который затем вызывает operator() для каждого элемента.

2 голосов
/ 19 февраля 2011

Вы можете bind1st указатель this, чтобы получить функтор, примененный к вашему процессору:

std::foreach( instructList.begin(), instructList.end(),
      std::bind1st
          ( std::mem_fun( &CChipSet::pushInstruction )
          , this 
          )
      );

(Примечание: я намеренно оставил подчеркивание от вашего _instructionList. Это не разрешено.)

2 голосов
/ 19 февраля 2011

Используйте boost::bind как,

std::for_each(/*..*/, /*..*/,
            boost::bind(&Chipset::pushInstruction, this, _1));
...