Class template multiple inheritance and function overloading - c++

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.

Related

g++ std::variant seems can't support user class with std::atomic/std::mutex variable member (with detail/code)

If I have a class with std::atomic_bool or std::mutex member for example, and if I put this class inside std::variant, my g++ will complain with "no matching function for call to std::variant<....>". Now I have to declare my std::mutex member to be static.
g++ (GCC) 7.3.1 20180303 (Red Hat 7.3.1-5) Copyright (C) 2017 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Actual code
#include <iostream>
#include <variant>
#include <mutex>
enum class enFixEngineRunMode {
eFixModeStreet // Fix connection side as initiator/client
,eFixModeStreetStandAlone // Fix connection side as initiator/client
,eFixModeStreetAccpt // Fix connection side as acceptor/server
,eFixModeStreetAccptStandAlone // Fix connection side as acceptor/server
,eFixModeClient // Fix connection side as acceptor/client
,eFixModeClientStandAlone // Fix connection side as acceptor/client
,eFixModeClientInit // Fix connection side as initiator/server
,eFixModeClientInitStandAlone // Fix connection side as initiator/server
,eFixModeInvalid
};
struct FOO {
FOO(int any) { }
void operator()() const {
std::cout << "FOO2" << std::endl;
}
};
template <enum enFixEngineRunMode>
struct BAR {
BAR(double any) { }
void operator()() const {
std::cout << "BAR2" << std::endl;
}
std::mutex m_metux;
};
template<>
struct BAR<enFixEngineRunMode::eFixModeStreetStandAlone> {
BAR(double any) { }
void operator()() const {
std::cout << "eFixModeStreetStandAlone" << std::endl;
}
};
using EngineImpl = std::variant<BAR<enFixEngineRunMode::eFixModeStreet>
, BAR<enFixEngineRunMode::eFixModeStreetStandAlone>
, BAR<enFixEngineRunMode::eFixModeStreetAccpt>
, BAR<enFixEngineRunMode::eFixModeStreetAccptStandAlone>
, BAR<enFixEngineRunMode::eFixModeClient>
, BAR<enFixEngineRunMode::eFixModeClientStandAlone>
, BAR<enFixEngineRunMode::eFixModeClientInit>
, BAR<enFixEngineRunMode::eFixModeClientInitStandAlone>
, BAR<enFixEngineRunMode::eFixModeInvalid>>;
struct Engine {
Engine() : m_engine([&] {
int i = 2;
if (1 == i)
return EngineImpl(BAR<enFixEngineRunMode::eFixModeStreetStandAlone>(0.0));
else return EngineImpl(BAR<enFixEngineRunMode::eFixModeStreet>(0.0));
}()) {}
void operator()() const {
std::visit([](auto const& e){ e(); }, m_engine);
}
EngineImpl m_engine;
};
int main(int argc, const char *argv[], char** env)
{
Engine e;
e();
return 0;
}
compilation error:
variantMain2.cpp:57:70: error: no matching function for call to ‘std::variant<BAR<(enFixEngineRunMode)0>, BAR<(enFixEngineRunMode)1>, BAR<(enFixEngineRunMode)2>, BAR<(enFixEngineRunMode)3>, BAR<(enFixEngineRunMode)4>, BAR<(enFixEngineRunMode)5>, BAR<(enFixEngineRunMode)6>, BAR<(enFixEngineRunMode)7>, BAR<(enFixEngineRunMode)8> >::variant(BAR<(enFixEngineRunMode)0>)’
else return EngineImpl(BAR<enFixEngineRunMode::eFixModeStreet>(0.0));
^
In file included from variantMain2.cpp:2:0:
/opt/rh/devtoolset-7/root/usr/include/c++/7/variant:986:2: note: candidate: template<long unsigned int _Np, class _Up, class ... _Args, class> constexpr std::variant<_Types>::variant(std::in_place_index_t<_Np>, std::initializer_list<_Up>, _Args&& ...)
variant(in_place_index_t<_Np>, initializer_list<_Up> __il,
^~~~~~~
/opt/rh/devtoolset-7/root/usr/include/c++/7/variant:986:2: note: template argument deduction/substitution failed:
variantMain2.cpp:57:70: note: ‘BAR<(enFixEngineRunMode)0>’ is not derived from ‘std::in_place_index_t<_Idx>’
else return EngineImpl(BAR<enFixEngineRunMode::eFixModeStreet>(0.0));
^
In file included from variantMain2.cpp:2:0:
/opt/rh/devtoolset-7/root/usr/include/c++/7/variant:977:2: note: candidate: template<long unsigned int _Np, class ... _Args, class> constexpr std::variant<_Types>::variant(std::in_place_index_t<_Np>, _Args&& ...)
variant(in_place_index_t<_Np>, _Args&&... __args)
Because std::variant is not an aggregate, it must move its arguments into its internal storage, and std::mutex is not movable (because doing so would break any concurrent users). Your choices are to make BAR movable (e.g., by storing a std::unique_ptr<std::mutex>), or to avoid the move by using std::in_place_type to construct the object inside the variant.

Call of overloaded function is ambiguous although different namespace

I do understand why the following would be a problem if no namespaces were used. The call would be ambiguous indeed. I thought "using stD::swap;" would define which method to use.
Why does it work for "int" but not a "class"?
#include <memory>
namespace TEST {
class Dummy{};
void swap(Dummy a){};
void sw(int x){};
}
namespace stD {
void swap(TEST::Dummy a){};
void sw(int x){};
class aClass{
public:
void F()
{
using stD::swap;
TEST::Dummy x;
swap(x);
}
void I()
{
using stD::sw;
int b = 0;
sw(b);
}
};
}
This is the error message:
../src/Test.h: In member function ‘void stD::aClass::F()’:
../src/Test.h:26:9: error: call of overloaded ‘swap(TEST::Dummy&)’ is ambiguous
swap(x);
^
../src/Test.h:26:9: note: candidates are:
../src/Test.h:17:6: note: void stD::swap(TEST::Dummy)
void swap(TEST::Dummy a){};
^
../src/Test.h:10:6: note: void TEST::swap(TEST::Dummy)
void swap(Dummy a){};
^
I thank you very much in advance for an answer.
This line is using argument dependent lookup
TEST::Dummy x;
swap(x);
So it will find both void stD::swap(TEST::Dummy) as well as void TEST::swap(TEST::Dummy) because x carries the TEST:: namespace.
In the latter case int b = 0; the variable b is not in a namespace, so the only valid function to call would be stD::sw due to your using statement.

Function pointers to non static member functions

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

C++ Template Class with Template Constructor

I tried to implement Properties in c++. I don't no why but if I want to compile my code there are quite a lot of errors. The main Idea was, that a template class and the tamplate constructor will give the requirement Informations.
I would be grateful if somebody could help me!
Compiling Message:
pi#raspberrypi ~/dev/property $ gcc -std=c++0x -o PropertyTest2 PropertyTest2.cpp
PropertyTest2.cpp:22:16: error: expected ‘;’ at end of member declaration
PropertyTest2.cpp:22:19: error: expected unqualified-id before ‘<’ token
PropertyTest2.cpp: In function ‘int main()’:
PropertyTest2.cpp:34:20: error: use of deleted function ‘PropertyTestClass::PropertyTestClass()’
PropertyTest2.cpp:8:7: error: ‘PropertyTestClass::PropertyTestClass()’ is implicitly deleted because the default definition would be ill-formed:
PropertyTest2.cpp:8:7: error: no matching function for call to ‘Property<int>::Property()’
PropertyTest2.cpp:8:7: note: candidates are:
Property4.cpp:21:2: note: template<int (** G)(), void (** S)(int&)> Property::Property()
Property4.cpp:6:7: note: constexpr Property<int>::Property(const Property<int>&)
Property4.cpp:6:7: note: candidate expects 1 argument, 0 provided
Property4.cpp:6:7: note: constexpr Property<int>::Property(Property<int>&&)
Property4.cpp:6:7: note: candidate expects 1 argument, 0 provided
PropertyTest2.cpp:38:20: error: no matching function for call to ‘Property<int>::Set(int)’
PropertyTest2.cpp:38:20: note: candidate is:
Property4.cpp:30:7: note: void Property<T>::Set(T&) [with T = int]
Property4.cpp:30:7: note: no known conversion for argument 1 from ‘int’ to ‘int&’
Property Class (Property.cpp)
#ifndef __PROPERTY_FH__
#define __PROPERTY_FH__
template <class T>
class Property {
private:
typedef T (*TGetter)(void);
typedef void (*TSetter)(T &);
TGetter Getter;
TSetter Setter;
public:
typedef T type;
template<TGetter *G,
TSetter *S
>
Property() {
this->Getter = G;
this->Setter = S;
}
T Get(void) {
return (this->Getter)();
}
void Set(T &value) {
(this->Setter)(value);
}
};
#endif
Testing file (PropertyTest.cpp):
#ifndef __PROPERTY_TEST_FH__
#define __PROPERTY_TEST_FH__
#include <iostream>
#include "Property.cpp"
class PropertyTestClass {
private:
// ReadWrite Property for age
int _age;
int AgeGetter(void) {
return this->_age;
}
void AgeSetter(int &value) {
this->_age = value;
}
public:
// ReadWrite Property for age
Property<int> age<&PropertyTestClass::AgeGetter, &PropertyTestClass::AgeSetter>;
};
#endif
/**
* Program Entry
**/
int main() {
std::cout << "Property Test Programm\n\n";
PropertyTestClass propTest;
std::cout << "ReadWrite Property for age\n";
propTest.age.Set(5);
std::cout << propTest.age.Get() << "\n";
return 0;
}
Ok, this time fixed all the problems in your code.
Property.cpp:
#ifndef __PROPERTY_FH__
#define __PROPERTY_FH__
#include <boost/function.hpp>
template <class T>
class Property {
private:
typedef boost::function <T()> TGetter;
typedef boost::function <void(const T&)> TSetter;
TGetter Getter;
TSetter Setter;
public:
typedef T type;
Property(TGetter G, TSetter S) {
this->Getter = G;
this->Setter = S;
}
T Get(void) {
return (this->Getter)();
}
void Set(const T &value) {
(this->Setter)(value);
}
};
#endif
PropertyTests.cpp:
#ifndef __PROPERTY_TEST_FH__
#define __PROPERTY_TEST_FH__
#include <iostream>
#include <boost/bind.hpp>
#include "Property.cpp"
class PropertyTestClass {
private:
// ReadWrite Property for age
int _age;
int AgeGetter() {
return this->_age;
}
void AgeSetter(const int &value) {
this->_age = value;
}
public:
// ReadWrite Property for age
Property<int> age;
PropertyTestClass() : age(
boost::bind(&PropertyTestClass::AgeGetter, this),
boost::bind(&PropertyTestClass::AgeSetter, this, _1))
{}
};
#endif
/**
* Program Entry
**/
int main() {
std::cout << "Property Test Programm\n\n";
PropertyTestClass propTest;
std::cout << "ReadWrite Property for age\n";
propTest.age.Set(5);
std::cout << propTest.age.Get() << "\n";
return 0;
}
Output:
$ ./a.out
Property Test Programm
ReadWrite Property for age
5

C++ 11 Thread initialization with member functions compiling error [duplicate]

This question already has answers here:
Start thread with member function
(5 answers)
Closed 9 years ago.
I'm just starting to use C++ 11 threads and I've been struggling on a (probably silly) error.
This is my example program:
#include <iostream>
#include <thread>
#include <future>
using namespace std;
class A {
public:
A() {
cout << "A constructor\n";
}
void foo() {
cout << "I'm foo() and I greet you.\n";
}
static void foo2() {
cout << "I'm foo2() and I am static!\n";
}
void operator()() {
cout << "I'm the operator(). Hi there!\n";
}
};
void hello1() {
cout << "Hello from outside class A\n";
}
int main() {
A obj;
thread t1(hello1); // it works
thread t2(A::foo2); // it works
thread t3(obj.foo); // error
thread t4(obj); // it works
t1.join();
t2.join();
t3.join();
t4.join();
return 0;
}
Is it possible to start a thread from a pure member function? If it is not, how can I wrap my foo function from object obj to be able to create such thread?
Thanks in advance!
This is the compiling error:
thread_test.cpp: In function ‘int main()’:
thread_test.cpp:32:22: error: no matching function for call to ‘std::thread::thread()’
thread_test.cpp:32:22: note: candidates are:
/usr/include/c++/4.6/thread:133:7: note: std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (A::*)(), _Args = {}]
/usr/include/c++/4.6/thread:133:7: note: no known conversion for argument 1 from ‘’ to ‘void (A::*&&)()’
/usr/include/c++/4.6/thread:128:5: note: std::thread::thread(std::thread&&)
/usr/include/c++/4.6/thread:128:5: note: no known conversion for argument 1 from ‘’ to ‘std::thread&&’
/usr/include/c++/4.6/thread:124:5: note: std::thread::thread()
/usr/include/c++/4.6/thread:124:5: note: candidate expects 0 arguments, 1 provided
You need a callable object taking no parameters, so
thread t3(&A::foo, &obj);
should do the trick. This has the effect of creating a callable entity which calls A::foo on obj.
The reason is that a non-static member function of A takes an implicit first parameter of type (possibly cv qualified) A*. When you call obj.foo() you are effectively calling A::foo(&obj). Once you know that, the above incantation makes perfect sense.