Function pointers to non static member functions - c++

Error:
C:\testa\game.cpp|147|error: no matching function for call to 'game::register_handler(PacketFamily, PacketAction,
<unresolved overloaded function type>)'|
Heres part of the code since it's too big.
I had to typedef handler_callback inside class game otherwise one of the two would be undefined for the other.
game.h
class game
{
typedef bool (game::*handler_callback)(PacketReader reader);
public:
bool default_handler_init (PacketReader reader);
void register_default_handlers();
void register_handler(PacketFamily family, PacketAction action,handler_callback callback);
};
game.cpp
void game::register_default_handlers()
{
register_handler(PACKET_F_INIT, PACKET_A_INIT,default_handler_init);
}
void game::register_handler(PacketFamily family, PacketAction action,handler_callback callback)
{
handlers.insert(std::make_pair(std::make_pair(family, action), callback));
}

I expanded the OP's code to the following so that it would compile:
class PacketReader {};
class PacketFamily {};
class PacketAction {};
const PacketFamily PACKET_F_INIT;
const PacketAction PACKET_A_INIT;
class game
{
typedef bool (game::*handler_callback)(PacketReader reader);
public:
bool default_handler_init (PacketReader reader);
void register_default_handlers();
void register_handler(PacketFamily family, PacketAction action, handler_callback callback);
};
void game::register_default_handlers()
{
register_handler(PACKET_F_INIT, PACKET_A_INIT, default_handler_init);
}
void game::register_handler(PacketFamily family, PacketAction action, handler_callback callback)
{
//handlers.insert(std::make_pair(std::make_pair(family, action), callback));
}
Compiling with g++ using the command g++ -c -Wall -std=c++11 test.cpp yields the following errors:
test.cpp: In member function ‘void game::register_default_handlers()’:
test.cpp:18:71: error: no matching function for call to ‘game::register_handler(const PacketFamily&, const PacketAction&, <unresolved overloaded function type>)’
register_handler(PACKET_F_INIT, PACKET_A_INIT,default_handler_init);
^
test.cpp:18:71: note: candidate is:
test.cpp:13:10: note: void game::register_handler(PacketFamily, PacketAction, game::handler_callback)
void register_handler(PacketFamily family, PacketAction action,handler_callback callback);
^
test.cpp:13:10: note: no known conversion for argument 3 from ‘<unresolved overloaded function type>’ to ‘game::handler_callback {aka bool (game::*)(PacketReader)}’
Anyway, to fix the problem, add &game:: to the call to register_handler:
register_handler(PACKET_F_INIT, PACKET_A_INIT,&game::default_handler_init);

Related

Opaque error message for Hello World LLVM pass in C++

I wrote a simple Hello World LLVM pass using the new pass manager.
It is important to note that I did not obtain the entire LLVM source and write the pass somewhere in this source tree.
Instead I installed llvm with
sudo apt install llvm
However when I want to compile my pass code to a dynamic library to run it with opt as a plugin I get the following error message (and yes, later on I will also use cmake for this but it gave me a similar error):
$ clang -shared -I/usr/include/llvm-13 -I/usr/include/llvm-c-13 -o libpass_test.so pass_test.cpp
In file included from pass_test.cpp:1:
In file included from /usr/include/llvm-13/llvm/IR/PassManager.h:48:
/usr/include/llvm-13/llvm/IR/PassManagerInternal.h:85:16: error: member reference base type 'bool (llvm::StringRef, llvm::PassManager<llvm::Function> &, llvm::ArrayRef<llvm::PassBuilder::PipelineElement>)' is not a structure or union
return Pass.run(IR, AM, ExtraArgs...);
~~~~^~~~
/usr/include/llvm-13/llvm/IR/PassManagerInternal.h:67:12: note: in instantiation of member function 'llvm::detail::PassModel<llvm::Function, bool (&)(llvm::StringRef, llvm::PassManager<llvm::Function> &, llvm::ArrayRef<llvm::PassBuilder::PipelineElement>), llvm::PreservedAnalyses, llvm::AnalysisManager<llvm::Function>>::run' requested here
explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {}
^
/usr/include/llvm-13/llvm/IR/PassManager.h:547:29: note: in instantiation of member function 'llvm::detail::PassModel<llvm::Function, bool (&)(llvm::StringRef, llvm::PassManager<llvm::Function> &, llvm::ArrayRef<llvm::PassBuilder::PipelineElement>), llvm::PreservedAnalyses, llvm::AnalysisManager<llvm::Function>>::PassModel' requested here
Passes.emplace_back(new PassModelT(std::forward<PassT>(Pass)));
^
pass_test.cpp:29:6: note: in instantiation of function template specialization 'llvm::PassManager<llvm::Function>::addPass<bool (&)(llvm::StringRef, llvm::PassManager<llvm::Function> &, llvm::ArrayRef<llvm::PassBuilder::PipelineElement>)>' requested here
FPM.addPass(passHook);
^
In file included from pass_test.cpp:1:
In file included from /usr/include/llvm-13/llvm/IR/PassManager.h:48:
/usr/include/llvm-13/llvm/IR/PassManagerInternal.h:88:44: error: type 'bool (&)(llvm::StringRef, llvm::PassManager<llvm::Function> &, llvm::ArrayRef<llvm::PassBuilder::PipelineElement>)' cannot be used prior to '::' because it has no members
StringRef name() const override { return PassT::name(); }
^
/usr/include/llvm-13/llvm/IR/PassManagerInternal.h:67:12: note: in instantiation of member function 'llvm::detail::PassModel<llvm::Function, bool (&)(llvm::StringRef, llvm::PassManager<llvm::Function> &, llvm::ArrayRef<llvm::PassBuilder::PipelineElement>), llvm::PreservedAnalyses, llvm::AnalysisManager<llvm::Function>>::name' requested here
explicit PassModel(PassT Pass) : Pass(std::move(Pass)) {}
^
/usr/include/llvm-13/llvm/IR/PassManager.h:547:29: note: in instantiation of member function 'llvm::detail::PassModel<llvm::Function, bool (&)(llvm::StringRef, llvm::PassManager<llvm::Function> &, llvm::ArrayRef<llvm::PassBuilder::PipelineElement>), llvm::PreservedAnalyses, llvm::AnalysisManager<llvm::Function>>::PassModel' requested here
Passes.emplace_back(new PassModelT(std::forward<PassT>(Pass)));
^
pass_test.cpp:29:6: note: in instantiation of function template specialization 'llvm::PassManager<llvm::Function>::addPass<bool (&)(llvm::StringRef, llvm::PassManager<llvm::Function> &, llvm::ArrayRef<llvm::PassBuilder::PipelineElement>)>' requested here
FPM.addPass(passHook);
^
2 errors generated.
The source code is this:
pass_test.h:
#ifndef PASS_TEST_H
#define PASS_TEST_H
using namespace llvm;
class PassTest : public PassInfoMixin<PassTest> {
public:
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
};
#endif
pass_test.cpp:
#include <llvm/IR/PassManager.h>
#include <llvm/Passes/PassBuilder.h>
#include <llvm/Passes/PassPlugin.h>
#include <llvm/Support/raw_ostream.h>
#include "pass_test.h"
//------------------------------------------------------------------------------
// The pass functionality
//------------------------------------------------------------------------------
PreservedAnalyses PassTest::run(Function &F, FunctionAnalysisManager &AM)
{
errs() << F.getName() << "\n";
return PreservedAnalyses::all();
}
//------------------------------------------------------------------------------
// Register the pass as a plugin for opt
//------------------------------------------------------------------------------
// the hook of my pass for opt
bool passHook(StringRef Name, FunctionPassManager &FPM,
ArrayRef<PassBuilder::PipelineElement>)
{
if (Name != "pass_test")
return false;
FPM.addPass(passHook);
return true;
}
// the pass builder hook using my pass hook
void builderHook(PassBuilder &PB)
{
PB.registerPipelineParsingCallback(passHook);
}
// information for this specific pass
llvm::PassPluginLibraryInfo getPassTestPluginInfo()
{
return {LLVM_PLUGIN_API_VERSION, "pass_test",
LLVM_VERSION_STRING, builderHook};
}
// public entry for my pass
extern "C" LLVM_ATTRIBUTE_WEAK llvm::PassPluginLibraryInfo
llvmGetPassPluginInfo()
{
return getPassTestPluginInfo();
}
I am happy for any hint what the actual problem is because I don't understand what exactly this error message is telling me.

Class template multiple inheritance and function overloading

Why are the function calls to waitForEvent in main below ambiguous?
#include <iostream>
struct Event1 { char c1[1]; };
struct Event2 { char c2[2]; };
template<class Event> struct EventSource
{
void waitForEvent(Event e) { std::cout << sizeof(e) << "\n"; };
};
typedef EventSource<Event1> Event1Source;
typedef EventSource<Event2> Event2Source;
struct Event12Source : public Event1Source, public Event2Source {};
int main()
{
Event12Source source;
source.waitForEvent(Event1());
source.waitForEvent(Event2());
return 0;
}
Compiling it I get the following errors:
user#AHERLADUSERVM2:~/test/TemplateMultipleMethodInheritance$ g++ test.cpp test.cpp: In function ‘int main()’: test.cpp:19:12: error: request for member ‘waitForEvent’ is ambiguous
source.waitForEvent(Event1());
^ test.cpp:7:10: note: candidates are: void EventSource<Event>::waitForEvent(Event) [with Event = Event2]
void waitForEvent(Event e) { std::cout << sizeof(e) << "\n"; };
^ test.cpp:7:10: note: void EventSource<Event>::waitForEvent(Event) [with Event = Event1] test.cpp:20:12: error: request for member ‘waitForEvent’ is ambiguous
source.waitForEvent(Event2());
^ test.cpp:7:10: note: candidates are: void EventSource<Event>::waitForEvent(Event) [with Event = Event2]
void waitForEvent(Event e) { std::cout << sizeof(e) << "\n"; };
^ test.cpp:7:10: note: void EventSource<Event>::waitForEvent(Event) [with Event = Event1]
(Why) is this not a simple case of function overloading resolution?
Thanks,
Damian
This may not be what you want, but it will solve the ambiguity
source.EventSource<Event1>::waitForEvent(Event1());
source.EventSource<Event2>::waitForEvent(Event2());
Also, if you are ever tempted to add a base class to Event1 and Event2, be aware of this
Because overloading does not work with inheritance. The derived class inherited the same function from two base classes which ambiguous.

Compile error with C++11 std::bind and auto for Callback function parameter

Hi I am having an issue compiling the following code. I am using auto and std::bind to bind a callback function with arguments. However, after passing this callback function as a parameter, it has issues compiling. Do you see an issue with the function declarations below:
#include <iostream>
#include <functional>
using namespace std;
class VmapPlayer
{
public:
void startPlayback();
void playAdBreak(int adBreak, void (VmapPlayer::*callback)());
void playSingleAd(int ad, void (VmapPlayer::*callback)(int adBreak, void (VmapPlayer::*cb)()));
};
void VmapPlayer::playSingleAd(int ad, void (VmapPlayer::*callback)(int adBreak, void (VmapPlayer::*cb)()))
{
cout << "i am here" << endl;
// OPTION #1 I would like to call this function
//(this->*callback)(adBreak, cb);
// OPTION #2 I would like this call this function without the params:
//(this->*callback)();
}
void VmapPlayer::playAdBreak(int adBreak, void (VmapPlayer::*callback)())
{
auto cb = std::bind(&VmapPlayer::playAdBreak, adBreak, callback);
playSingleAd(123, cb);
}
void VmapPlayer::startPlayback()
{
playAdBreak(456, &VmapPlayer::startPlayback);
}
int main()
{
VmapPlayer p;
p.startPlayback();
return 0;
}
Please see below for the compile error log:
main.cpp||In member function 'void VmapPlayer::playAdBreak(int, void (VmapPlayer::*)())':|
main.cpp|28|error: no matching function for call to 'VmapPlayer::playSingleAd(int, std::_Bind<std::_Mem_fn<void (VmapPlayer::*)(int, void (VmapPlayer::*)())>(int, void (VmapPlayer::*)())>&)'|
main.cpp|28|note: candidate is:|
main.cpp|14|note: void VmapPlayer::playSingleAd(int, void (VmapPlayer::*)(int, void (VmapPlayer::*)()))|
main.cpp|14|note: no known conversion for argument 2 from 'std::_Bind<std::_Mem_fn<void (VmapPlayer::*)(int, void (VmapPlayer::*)())>(int, void (VmapPlayer::*)())>' to 'void (VmapPlayer::*)(int, void (VmapPlayer::*)())'|
||=== Build finished: 1 errors, 0 warnings (0 minutes, 0 seconds) ===|
I supposed my question can be simplified as:
What does the function declaration for playSingleAd() need to be in order to compile the following successfully?:
void VmapPlayer::playAdBreak(int adBreak, void (VmapPlayer::*callback)())
{
auto cb = std::bind(&VmapPlayer::playAdBreak, adBreak, callback);
playSingleAd(123, cb);
}
When you bind a method to fully-supplied parameters, the resulting functor takes no arguments. In your code, playSingleAd takes a function pointer that takes as an argument, a function pointer whose arguments are to be supplied when called. Because you already bound the arguments to that function pointer, the arguments thereto cannot not be specified in the function signature.
Anyway, your code can be improved with the use of std::function. Moreover, the function will have to take the instance as an argument, as shown in the implementation of playSingleAd below:
class VmapPlayer
{
public:
void startPlayback();
void playAdBreak(int adBreak, void (VmapPlayer::*callback)());
void playSingleAd(int ad, std::function<void (VmapPlayer&)>);
};
void VmapPlayer::playSingleAd(int, std::function<void (VmapPlayer&)> callback)
{
cout << "i am here" << endl;
callback(*this);
}
void VmapPlayer::playAdBreak(int adBreak, void (VmapPlayer::*callback)())
{
using namespace std::placeholders;
auto cb = std::bind(&VmapPlayer::playAdBreak, _1, adBreak, callback);
playSingleAd(123, cb);
}

unable to overload virtual function

I have a Network class, which I want two virtual functions which I am going to overload: airtime() and airtime(std::vector<int> freq_bins);
I define the class, and the functions at the bottom:
class Network
{
public:
// Properties of the network protocol
std::string _name;
std::vector<float> _channels;
float _bandwidth;
float _txtime;
// Properties of the specific network
int _id;
macs::mac_t _mac;
protocols::protocol_t _protocol;
bool _static;
float _desired_airtime;
float _act_airtime;
bool _active;
// Constructor
Network();
virtual float airtime() { };
virtual float airtime(std::vector<int> freq_bins) { };
};
Now, I have a second class which I want to overload them. Here is the header of this class:
#ifndef _CSMA_H_
#define _CSMA_H_
#include <string>
#include <vector>
#include <map>
#include "MACs.h"
#include "Protocols.h"
#include "Network.h"
class CSMA : public Network
{
public:
float center_freq;
CSMA();
float airtime();
float airtime(std::vector<int> freq_bins);
};
#endif
I then define them in CSMA.cpp:
#include <iostream>
#include <string>
#include <vector>
#include "MACs.h"
#include "Protocols.h"
#include "Network.h"
#include "Simulator.h"
#include "CSMA.h"
extern Simulator sim;
CSMA::CSMA() {
_mac = macs::CSMA;
}
float CSMA::airtime() {
return _act_airtime;
}
float CSMA::airtime(std::vector<int> freq_bins) {
return 1;
}
I get the warning on returning values, that's not a problem. But the errors I get when trying to compile this, I don't understand:
g++ -o hce_sim hce_sim.cpp Network.cpp CSMA.cpp -Wall
In file included from hce_sim.cpp:2:
Network.h:54: error: ‘virtual float Network::airtime(std::vector<int, std::allocator<int> >)’ cannot be overloaded
Network.h:49: error: with ‘virtual float Network::airtime(std::vector<int, std::allocator<int> >)’
Network.h: In member function ‘virtual float Network::airtime()’:
Network.h:53: warning: no return statement in function returning non-void
Network.h: In member function ‘virtual float Network::airtime(std::vector<int, std::allocator<int> >)’:
Network.h:54: warning: no return statement in function returning non-void
In file included from Network.cpp:6:
Network.h:54: error: ‘virtual float Network::airtime(std::vector<int, std::allocator<int> >)’ cannot be overloaded
Network.h:49: error: with ‘virtual float Network::airtime(std::vector<int, std::allocator<int> >)’
Network.h: In member function ‘virtual float Network::airtime()’:
Network.h:53: warning: no return statement in function returning non-void
Network.h: In member function ‘virtual float Network::airtime(std::vector<int, std::allocator<int> >)’:
Network.h:54: warning: no return statement in function returning non-void
In file included from CSMA.cpp:6:
Network.h:54: error: ‘virtual float Network::airtime(std::vector<int, std::allocator<int> >)’ cannot be overloaded
Network.h:49: error: with ‘virtual float Network::airtime(std::vector<int, std::allocator<int> >)’
I created a more simplified program to try and understand why I get this error, yet this simplified program works:
#include <iostream>
#include <vector>
class Base {
public:
Base() { }
virtual void check() { }
virtual void check(bool it) { }
};
class First : public Base {
public:
First() { }
void check() {
std::cout << "You are in check(void) !\n";
}
void check(bool it) {
std::cout << "You are in check(bool) !\n";
}
};
int main() {
First f;
f.check();
f.check(true);
}
Does anyone have any insight here?
Try pure virtual function declarations.
virtual float airtime() = 0;
virtual float airtime(std::vector<int> freq_bins) = 0;
The reason it fails is that you definitions are incorrect, they don't return anything even though you have specified that it should return float.
Tip: You really shouldn't expose the internal state of your class like that. Do some googling on encapsulation.

How do I declare a C++ prototype with a void * pointer so that it can take any pointer type?

I want to create a function prototype in C++ so that there is a void * argument that can take pointers of any type. I know that this is possible in C. Is it possible in C++?
[EDIT] Here is a simplified version of the code that I am trying to get to work:
#include <stdio.h>
void func(void (f)(const void *))
{
int i = 3;
(*f)(&i);
}
void func_i(const int *i)
{
printf("i=%p\n",i);
}
void func_f(const float *f)
{
printf("f=%p\n",f);
}
void bar()
{
func(func_i);
}
And here is the compiler output:
$ g++ -c -Wall x.cpp
x.cpp: In function ‘void bar()’:
x.cpp:21: error: invalid conversion from ‘void (*)(const int*)’ to ‘void (*)(const void*)’
x.cpp:21: error: initializing argument 1 of ‘void func(void (*)(const void*))’
$ %
You may use void*, just as with C, but you'll need to cast your argument when calling it. I suggest you use a template function
template<typename T>
void doSomething(T* t) {...}
Yes.
int i = 345;
void * ptr = &i;
int k = *static_cast&lt int* &gt(ptr);
UPDATE ::
What you have shown in the code certainly cannot be done in C++.
Casting between void and any other must always be explicitly done.
Check these SO link for more details on what the C -standard has to say:
1) http://stackoverflow.com/questions/188839/function-pointer-cast-to-different-signature
2) http://stackoverflow.com/questions/559581/casting-a-function-pointer-to-another-type
How about:
void func(void *);
exactly like in C? : P