pm100
pm100

Reputation: 50180

std::function vs alias function pointer , why one wont compile

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

Answers (1)

Christophe
Christophe

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

Additional info

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

Related Questions