Reputation: 50180
Wanting to investigate the performance hit (if any) of std:function
.
I have this struct:
struct InstructionDescription
{
std::string name;
word mask;
word code;
std::function<void(Cpu*, word)> func;
word flags;
};
and I set up a vector of them like this
std::vector<InstructionDescription> instructions_{
{
{"clr", DD_MASK, 0005000, &Cpu::Clr},
{"clrb", DD_MASK, 0105000, &Cpu::Clr},
{"com", DD_MASK, 0005100, &Cpu::Com},
.....
Works fine. Now if I change the struct to use a function pointer:
using InstrFunc = void(*)(Cpu*, word);
struct InstructionDescription
{
std::string name;
word mask;
word code;
InstrFunc func;
word flags;
};
which as far as I can see should be equivalent. And yet I get
1>C:\work\pdp\mysim\mysim\instructions.h(60,50): error C2664: 'std::vector<Cpu::InstructionDescription,std::allocator<Cpu::InstructionDescription>>::vector(std::initializer_list<_Ty>,const _Alloc &)': cannot convert argument 1 from 'initializer list' to 'std::initializer_list<_Ty>'
1> with
1> [
1> _Ty=Cpu::InstructionDescription,
1> _Alloc=std::allocator<Cpu::InstructionDescription>
1> ]
1> and
1> [
1> _Ty=Cpu::InstructionDescription
1> ]
1>C:\work\pdp\mysim\mysim\instructions.h(60,50): message : Element '1': no conversion from 'initializer list' to '_Ty'
1> with
1> [
1> _Ty=Cpu::InstructionDescription
1> ]
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.25.28610\include\vector(512,5): message : see declaration of 'std::vector<Cpu::InstructionDescription,std::allocator<Cpu::InstructionDescription>>::vector'
1>Console.cpp
VS2019. VS GUI is also highlighting the std::vector line saying 'InstructionDescription' is unknown and that the function names are not accessible (&Cpu::Clr for example)
The Cpu
class is defined like:
struct Cpu {
void Clr(word) {};
void Com(word) {};
};
What am I doing wrong?
Upvotes: 3
Views: 129
Reputation: 73376
The std::function
is very convenient: it recognizes that &Cpu::Clr
is a member function whose first parameter will be a Cpu*
.
When you make it a function pointer, this doesn't work like this. You have to use a member function pointer:
using InstrFunc = void (Cpu::*)(word);
This is standard: std::function
nicely copes with pointers to member functions by adding a pointer to the class as first argument. Of course, when you call it, you have to provide that additional parameter:
Cpu cpu;
for (auto& i:instructions_) {
i.func(&cpu, i.code); // as simple as that with std::function
}
When you go for the pointer to member function, it's less convenient:
Cpu cpu;
for (auto& i:instructions) {
(cpu.*i.func)(i.code);
}
Online demo (you need to comment/ comment out the specific lines)
Upvotes: 6