C++ expression cannot be used as a function: (_f2)(arg); - c++

A few years ago i had my Open tibia server, it's old source engine, previous compiled at gcc 4.7+, already i try to compile it at newest debian, my gcc version is: 8.3.0 (Debian 8.3.0-6)
error: no match for call to ‘(Task) (Game*&)’
(*_f2)(arg);
error displays: expression cannot be used as a function
(_f2)(arg);
template<class ArgType>
class TCallList : public SchedulerTask{
public:
TCallList(
boost::function<bool(Game*, ArgType)> f1,
Task* f2,
std::list<ArgType>& call_list,
int64_t interval) :
_f1(f1), _f2(f2), _list(call_list), _interval(interval)
{
//
}
virtual void operator()(Game* arg)
{
if(_eventid != 0){
bool ret = _f1(arg, _list.front());
_list.pop_front();
if(ret){
if(_list.empty()){
//callback function
if(_f2){
(_f2)(arg);
delete _f2;
}
}
else{
//fire next task
SchedulerTask* newTask = new TCallList(_f1, _f2, _list, _interval);
newTask->setTicks(_interval);
newTask->setEventId(this->getEventId());
arg->addEvent(newTask);
}
}
}
}
private:
boost::function<bool(Game*, ArgType)> _f1;
Task* _f2;
std::list<ArgType> _list;
int64_t _interval;
};
template<class ArgType>
SchedulerTask* makeTask(int64_t ticks,
boost::function<bool(Game*, ArgType)>* f1,
std::list<ArgType>& call_list,
int64_t interval,
Task* f2)
{
TCallList<ArgType>* t = new TCallList<ArgType>(f1, f2, call_list, interval);
t->setTicks(ticks);
return t;
}
Scheduler.cpp
#ifndef __OTSERV_SCHEDULER_H__
#define __OTSERV_SCHEDULER_H__
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <functional>
#include "otsystem.h"
class Game;
class SchedulerTask {
public:
SchedulerTask() {
_eventid = 0;
_cycle = 0;
}
virtual ~SchedulerTask()
{
//
}
// definition to make sure lower cycles end up front
// in the priority_queue used in the scheduler
inline bool operator<(const SchedulerTask& other) const
{
return getCycle() > other.getCycle();
}
virtual void operator()(Game* arg) = 0;
virtual void setEventId(uint32_t id)
{
_eventid = id;
}
inline uint32_t getEventId() const
{
return _eventid;
}
virtual void setTicks(const int64_t ticks)
{
_cycle = OTSYS_TIME() + ticks;
}
inline int64_t getCycle() const
{
return _cycle;
}
protected:
uint32_t _eventid;
int64_t _cycle;
};
class TSchedulerTask : public SchedulerTask{
public:
TSchedulerTask(boost::function1<void, Game*> f) :
_f(f)
{
//
}
virtual ~TSchedulerTask()
{
//
}
virtual void operator()(Game* arg)
{
_f(arg);
}
protected:
boost::function1<void, Game*> _f;
};
SchedulerTask* makeTask(boost::function1<void, Game*> f);
SchedulerTask* makeTask(int64_t ticks, boost::function1<void, Game*> f);
class lessSchedTask : public std::binary_function<SchedulerTask*, SchedulerTask*, bool>{
public:
bool operator()(SchedulerTask*& t1, SchedulerTask*& t2)
{
return *t1 < *t2;
}
};
#endif

Related

Can't call class function from a template function class inside a template class

I am trying to create a pattern where an abstract class has several methods where all get the same member. The derived implementation is on a specific member type and the pattern should redundant the need to downcast the types.
The following is not working:
Assume these type classes
//--------------
// Data classes
//--------------
class TypeA
{
virtual int a() = 0;
};
class TypeB : public TypeA
{
int a() override
{
return 5;
}
};
Pattern:
//-------------------
// Base action class.
//-------------------
class ExampleBase
{
public:
virtual bool f1(TypeA& val) = 0;
virtual bool f2(TypeA& val) = 0;
};
//----------------------------------
// Base specific Typed action class.
//----------------------------------
template<class T>
class ExampleSpecific1 : public ExampleBase
{
public:
virtual bool specificF1(T& specificVal) = 0;
virtual bool specificF2(T& specificVal) = 0;
bool f1(TypeA& val) override
{
return fRunner<bool, specificF1>(val, false);
}
bool f2(TypeA& val) override
{
return fRunner<bool, specificF2>(val, false);
}
private:
// Run the specific function with the specific type
template<class S, S (*pf)(T& val)>
S fRunner(TypeA& val, S defaultValue)
{
S ret = defaultValue;
T& specificVal = dynamic_cast<T&>(val);
if (&specificVal != nullptr) {
ret = pf(specificVal);
}
return ret;
}
};
The implementation
//----------------------
// Class Implementation.
//----------------------
class ExampleImpl : public ExampleSpecific1<TypeB>
{
public:
bool specificF1(TypeB& specificVal) override
{
// Do something
}
bool specificF2(TypeB& specificVal) override
{
// Do something
}
};
Usage:
//-----------
// Class Use.
//-----------
void main()
{
ExampleImpl impl;
TypeB myVal;
TypeA& myBaseVal = myVal;
impl.f1(myBaseVal);
impl.f2(myBaseVal);
}
I get the following compilation error:
error C2672: 'ExampleSpecific1<TypeB>::fRunner': no matching overloaded function found
note: while compiling class template member function 'bool ExampleSpecific1<TypeB>::f2(TypeA &)'
note: see reference to function template instantiation 'bool ExampleSpecific1<TypeB>::f2(TypeA &)' being compiled
note: see reference to class template instantiation 'ExampleSpecific1<TypeB>' being compiled
error C2975: 'pf': invalid template argument for 'ExampleSpecific1<TypeB>::fRunner', expected compile-time constant expression
note: see declaration of 'pf'
A function template that does work (when the function is not inside a class):
Based on the previous example:
template<class T, bool (*pf1)(T& Val), bool (*pf2)(T& Val)>
class ExampleSpecific2 : public ExampleBase
{
public:
bool f1(TypeA& val) override
{
bool ret = false;
T& specificVal = dynamic_cast<T&>(val);
if (&specificVal != nullptr) {
ret = pf1(specificVal);
}
return ret;
}
bool f2(TypeA& val) override
{
bool ret = false;
T& specificVal = dynamic_cast< T&>(val);
if (&specificVal != nullptr) {
ret = pf2(specificVal);
}
return ret;
}
};
External functions:
bool extF1(TypeB& val)
{
// Do something.
}
bool extF2(TypeB& val)
{
// Do something.
}
Useage:
//-----------
// Class Use.
//-----------
void main()
{
TypeB myVal;
TypeA& myBaseVal = myVal;
ExampleSpecific2<TypeB, extF1, extF2> impl2;
impl2.f1(myBaseVal);
impl2.f2(myBaseVal);
}
In the example that does not work, I can implement the down cast in each of the implementation and then it works, but it is ugly and is not generic. In the working example I want the function to be in the internal implementation of the class and not external to it, this is important in more complicated scenarios, where the base class is calling several of the derived methods.
BTW I don't like this post Title, if you have a better suggestion that I like, this will be great.
Note :
main should return an int, not void
if (&specificVal != nullptr) will be always true, reference cannot be null.
I am not sur why you got this error message, with gcc I got :
no matching member function for call to 'fRunner'
Because pf type was bool (ExampleSpecific1<TypeB>::*)(TypeB &) which didn't match with S (*pf)(T& val). The first one need an class object.
So I just use the C++17 auto :
template<class S, auto pf>
S fRunner(TypeA& val, S defaultValue){...}
But you can use the full type if you want.
Next We need to call the member function. I don't like (nor remember) the member function call syntaxe, so I just use std::invoke of C++17. (see : https://en.cppreference.com/w/cpp/utility/functional/invoke)
Live : https://wandbox.org/permlink/rEqgLSwSjEfqRK2o
#include <iostream>
#include <vector>
//--------------
// Data classes
//--------------
class TypeA
{
virtual int a() = 0;
};
class TypeB : public TypeA
{
int a() override
{
return 5;
}
};
//-------------------
// Base action class.
//-------------------
class ExampleBase
{
public:
virtual bool f1(TypeA& val) = 0;
virtual bool f2(TypeA& val) = 0;
};
//----------------------------------
// Base specific Typed action class.
//----------------------------------
template<class T>
class ExampleSpecific1 : public ExampleBase
{
private:
// Run the specific function with the specific type
template<class S, auto pf>
S fRunner(TypeA& val, S defaultValue)
{
S ret = defaultValue;
T& specificVal = dynamic_cast<T&>(val);
ret = std::invoke(pf, *this, specificVal);
return ret;
}
public:
virtual bool specificF1(T& specificVal) = 0;
virtual bool specificF2(T& specificVal) = 0;
bool f1(TypeA& val) override
{
return this->fRunner<bool, &ExampleSpecific1<T>::specificF1>(val, false);
}
bool f2(TypeA& val) override
{
return this->fRunner<bool, &ExampleSpecific1<T>::specificF2>(val, false);
}
};
// Class Implementation.
//----------------------
class ExampleImpl : public ExampleSpecific1<TypeB>
{
public:
bool specificF1(TypeB& ) override
{
std::cout << "specificF1" << std::endl;
return true;
}
bool specificF2(TypeB& ) override
{
std::cout << "specificF2" << std::endl;
return true;
}
};
//-----------
// Class Use.
//-----------
int main()
{
ExampleImpl impl;
TypeB myVal;
TypeA& myBaseVal = myVal;
impl.f1(myBaseVal);
impl.f2(myBaseVal);
}
Pre C++17 : https://wandbox.org/permlink/HSGMy4zb4TgusESf
template<class S, S (ExampleSpecific1<T>::*pf)(T &)> // full type since auto is C++ 17
S fRunner(TypeA& val, S defaultValue)
{
S ret = defaultValue;
T& specificVal = dynamic_cast<T&>(val);
ret = (this->*pf)(specificVal); // Ugly pre 17
return ret;
}

dynamically call same named function with different return type

I have a situation here...
I want to design a Factory where I can call a function with same name and no parameters but return different data Types. Based on the SubClassName I need to instantiate the Object.
Need help or lead on any design pattern to follow?
EDIT:
An abstract pseudo code...
class parent{
public:
virtual string getName() = 0;
//some virtual function.. not sure how to design. As the return type is dynamic.
*** getValue(){}
};
class A : public parent{
int x;
public:
virtual string getName(){ return "A";}
virtual int getValue(){retun x;}
};
class B : public parent{
string s;
public:
virtual string getName(){ return "B";}
virtual string getValue(){ return s;}
};
void main(){
string callingClass = "B";
parent * arrayPtrs[2];
arrayPtrs[0] = new A;
arrayPtrs[1] = new B;
for (loop through array, through iterator i){
if(arrayPtrs[i]->getName == callingClass ){
cout<<arrayPtrs[i]->getValue;
}
}
}
In C++ a function can only have one return type at a time, and you cannot change that dynamically.
However - as suggested by #mch - you can use template specializations. Keep in mind though, that this method is not dynamic. Your functions will be generated at compile time.
If I understood your question correctly, maybe this can be of help.
class MyObject1
{
//...
};
class MyObject2
{
//...
};
template<typename T>
struct Factory
{
constexpr static T gen();
};
template<>
struct Factory<MyObject1>
{
constexpr static MyObject1 gen()
{
return MyObject1(/*... whatever parameters you see fit ...*/);
}
};
template<>
struct Factory<MyObject2>
{
constexpr static MyObject2 gen()
{
return MyObject2(/*... whatever parameters you see fit ...*/);
}
};
int main()
{
auto myObj = Factory<MyObject1>::gen();
return 0;
}
Although this method seems fairly useless to me. You could simply call the desired constructor instead of this.
But then again, I'm not sure if this is what you thought of. If I made any mistakes please feel free, to correct me. I'll try to edit my answer best as I can.
EDIT:
To keep the virtual functionality too, the only way I can think of is type erasure: see https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Type_Erasure
The closest I could get to what you've asked for is this:
#include <iostream>
#include <string>
#include <any>
class parent {
public:
// you can use this too but I think type checking is more handy
// see in main function
/* virtual std::string getName() const = 0; */
virtual std::any getValue() const = 0;
};
class A : public parent {
public:
typedef int value_type;
private:
value_type x;
public:
A(value_type x) :
x(x)
{}
/* virtual std::string getName() const override { return "A"; } */
virtual std::any getValue() const override
{ return this->x; }
};
class B : public parent {
public:
typedef std::string value_type;
private:
value_type s;
public:
B(const value_type& s) :
s(s)
{}
/* virtual std::string getName() const override { return "B"; } */
virtual std::any getValue() const override
{ return this->s; }
};
int main(){
using callingClass = A;
parent* arrayPtrs[2];
arrayPtrs[0] = new A(42);
arrayPtrs[1] = new B("my string");
for (unsigned i = 0; i < sizeof(arrayPtrs) / sizeof(parent*); ++i)
{
// Note:
// dynamic cast will return nullptr if $callingClass
// is not a derived class
if (dynamic_cast<callingClass*>(arrayPtrs[i]))
std::cout << std::any_cast<callingClass::value_type>(arrayPtrs[i]->getValue()) << std::endl;
}
return 0;
}
I hope this one helps.
Note, that I used dynamic_cast to check the correct type. If you know a better solution, you can use that, too. But under these circumstances I couldn't think of any better.
EDIT2:
#include <iostream>
#include <string>
#include <tuple>
class some
{
using id = size_t;
template<typename T>
struct type { static void id() { } };
template<typename T>
static id type_id() { return reinterpret_cast<id>(&type<T>::id); }
template<typename T>
using decay = typename std::decay<T>::type;
template<typename T>
using none = typename std::enable_if<!std::is_same<some, T>::value>::type;
struct base
{
virtual ~base() { }
virtual bool is(id) const = 0;
virtual base *copy() const = 0;
} *p = nullptr;
template<typename T>
struct data : base, std::tuple<T>
{
using std::tuple<T>::tuple;
T &get() & { return std::get<0>(*this); }
T const &get() const& { return std::get<0>(*this); }
bool is(id i) const override { return i == type_id<T>(); }
base *copy() const override { return new data{get()}; }
};
template<typename T>
T &stat() { return static_cast<data<T>&>(*p).get(); }
template<typename T>
T const &stat() const { return static_cast<data<T> const&>(*p).get(); }
template<typename T>
T &dyn() { return dynamic_cast<data<T>&>(*p).get(); }
template<typename T>
T const &dyn() const { return dynamic_cast<data<T> const&>(*p).get(); }
public:
some() { }
~some() { delete p; }
some(some &&s) : p{s.p} { s.p = nullptr; }
some(some const &s) : p{s.p->copy()} { }
template<typename T, typename U = decay<T>, typename = none<U>>
some(T &&x) : p{new data<U>{std::forward<T>(x)}} { }
some &operator=(some s) { swap(*this, s); return *this; }
friend void swap(some &s, some &r) { std::swap(s.p, r.p); }
void clear() { delete p; p = nullptr; }
bool empty() const { return p; }
template<typename T>
bool is() const { return p ? p->is(type_id<T>()) : false; }
template<typename T> T &&_() && { return std::move(stat<T>()); }
template<typename T> T &_() & { return stat<T>(); }
template<typename T> T const &_() const& { return stat<T>(); }
template<typename T> T &&cast() && { return std::move(dyn<T>()); }
template<typename T> T &cast() & { return dyn<T>(); }
template<typename T> T const &cast() const& { return dyn<T>(); }
template<typename T> operator T &&() && { return std::move(_<T>()); }
template<typename T> operator T &() & { return _<T>(); }
template<typename T> operator T const&() const& { return _<T>(); }
};
using any = some;
class parent {
public:
// you can use this too but I think type checking is more handy
/* virtual std::string getName() const = 0; */
virtual any getValue() const = 0;
};
class A : public parent {
public:
typedef int value_type;
private:
value_type x;
public:
A(value_type x) :
x(x)
{}
/* virtual std::string getName() const override { return "A"; } */
virtual any getValue() const override
{ return this->x; }
};
class B : public parent {
public:
typedef std::string value_type;
private:
value_type s;
public:
B(const value_type& s) :
s(s)
{}
/* virtual std::string getName() const override { return "B"; } */
virtual any getValue() const override
{ return this->s; }
};
int main(){
using callingClass = A;
parent* arrayPtrs[2];
arrayPtrs[0] = new A(42);
arrayPtrs[1] = new B("my string");
for (unsigned i = 0; i < sizeof(arrayPtrs) / sizeof(parent*); ++i)
{
// Note:
// dynamic cast will return nullptr if $callingClass
// is not a derived class
if (dynamic_cast<callingClass*>(arrayPtrs[i]))
std::cout << arrayPtrs[i]->getValue()._<callingClass::value_type>() << std::endl;
}
return 0;
}
This snipped is in case you cannot use C++17 features, and is based on:
any class

C++ Similar functions using different data types

I have two functions which are exactly the same, except that one of them uses a stack for its operations and the other one uses a queue:
void doQueue()
{
std::queue<int> q;
...
...
q.push(someValue);
...
...
int tmp = q.front();
q.pop()
}
void doStack()
{
std::stack<int> s;
...
...
s.push(someValue);
...
...
int tmp = s.top();
s.pop()
}
I want to eliminate duplicate code. As queue uses the front function to retrieve the first value and stack uses the top function, I thought that templates may not work since functions with different names have to be called.
My other idea was to create an interface which will be as a wrapper to both data structures and I can pass around the one that I need.:
class Data
{
public:
virtual void push(const int v) = 0;
virtual int pop() = 0;
};
class StackData : public Data
{
private:
std::stack<int> _stack;
public:
virtual void push(const int v) {_stack.push(v);}
virtual int pop()
{
int ret = _stack.top();
_stack.pop();
return ret;
}
};
class QueueData : public Data
{
private:
std::queue<int> _queue;
public:
virtual void push(const int v) {_queue.push(v);}
virtual int pop()
{
int ret = _queue.front();
_queue.pop();
return ret;
}
};
void doData(Data& dataType)
{
...
dataType.push(someValue);
...
int tmp = dataType.pop();
}
void doQueue()
{
QueueData queueData;
doData(queueData);
}
void doStack()
{
StackData stackData;
doData(stackData);
}
But I think there should be an easier and better way to perform this operation.
Here's one way - a wrapper template with partial specialisation on underlying container type:
#include <stack>
#include <queue>
template<class Container>
struct generic_sequence_ops;
template<class T, class UnderlyingContainer>
struct generic_sequence_ops<std::stack<T, UnderlyingContainer>>
{
using container_type = std::stack<T, UnderlyingContainer>;
using value_type = typename container_type::value_type;
generic_sequence_ops(container_type& c) : c(c) {}
void add_one(value_type v)
{
c.push(std::move(v));
}
void remove_one()
{
c.pop();
}
value_type& current()
{
return c.top();
}
container_type& c;
};
template<class T, class UnderlyingContainer>
struct generic_sequence_ops<std::queue<T, UnderlyingContainer>>
{
using container_type = std::queue<T, UnderlyingContainer>;
using value_type = typename container_type::value_type;
generic_sequence_ops(container_type& c) : c(c) {}
void add_one(value_type v)
{
c.push(std::move(v));
}
void remove_one()
{
c.pop();
}
value_type& current()
{
return c.back();
}
container_type& c;
};
template<class Container>
auto make_generic_sequence_ops(Container& cont)
{
return generic_sequence_ops<std::decay_t<Container>>(cont);
}
template<class Container>
int doContainer(Container& cont)
{
auto s = make_generic_sequence_ops(cont);
s.add_one(6);
int val = s.current();
s.remove_one();
return val;
}
int main()
{
std::queue<int> q;
std::stack<int> s;
doContainer(q);
doContainer(s);
}

How to create a generic template based factory?

I am using c++98. I want to create a generic factory which is template based, and the creator can take no parameter to create the target object, or one parameter.
/*<class.h> begins
#ifndef INCLUDED_CLASS
#define INCLUDED_CLASS
#include <iostream>
#include <boost/shared_ptr.hpp>
class A
{
public:
A() { _a = 27; }
void print() const { std::cout << "A is " << _a << "." << std::endl; }
protected:
int _a;
};
typedef boost::shared_ptr<A> APtr;
class AA : public A
{
public:
void print() const { std::cout << "AA is " << _a << "!" << std::endl; }
};
class B
{
public:
B(double b) { _b = b; }
void print() const { std::cout << "B is " << _b << "." << std::endl; }
protected:
double _b;
};
typedef boost::shared_ptr<B> BPtr;
class BB : public B
{
public:
BB(double b) : B(b) {};
void print() const { std::cout << "BB is " << _b << "!" << std::endl; }
};
#endif
/*<class.h> ends
/*<factory.h> begins
#ifndef INCLUDED_FACTORY
#define INCLUDED_FACTORY
#include <map>
#include <string>
#include <boost/shared_ptr.hpp>
template<class bT, class pT=void>
class Creator
{
public:
virtual bT* create() = 0;
virtual bT* create(const pT* param) = 0;
};
template <class bT, class pT>
struct CreatorPtr
{
typedef boost::shared_ptr< Creator<bT> > type;
};
template <class bT, class cT, class pT>
class CreatorImpl : public Creator<bT, pT>
{
public:
virtual bT* create() { return new cT; }
virtual bT* create(const pT* param) { return new cT(param); }
};
template<class bT, class pT=void>
class Factory
{
public:
virtual bT* create(const std::string& name) const = 0;
virtual bT* create(const std::string& name, const pT* param) const = 0;
protected:
Factory() {}
Factory(const Factory&) {}
Factory &operator=(const Factory&) { return *this; }
void registerCreator(const std::string& name, typename CreatorPtr<bT, pT>::type creator)
{ _table_creator[name] = creator; }
typedef std::map<std::string, typename CreatorPtr<bT, pT>::type> tableCreator;
typedef typename tableCreator::const_iterator citerTc;
citerTc begin() const { return _table_creator.begin(); }
citerTc end() const { return _table_creator.end(); }
citerTc find(const std::string& name) const { return _table_creator.find(name); }
protected:
tableCreator _table_creator;
};
class A;
class EngineA : public Factory<A>
{
public:
virtual A* create(const std::string& name) const
{
citerTc it = find(name);
if (it != end() && it->second)
{
return it->second->create();
}
else
return (A*)NULL;
}
static Factory<A>& get()
{
static EngineA instance;
instance.registerEngine();
return instance;
}
private:
virtual A* create(const std::string& name, const void* param) const { return (A*)NULL; }
private:
virtual void registerEngine();
};
void EngineA::registerEngine()
{
CreatorPtr<A, void>::type AACreator(new CreatorImpl<A, AA, void>);
registerCreator("AA", AACreator);
}
class B;
class EngineB : public Factory<B, double>
{
public:
virtual B* create(const std::string& name, const double* value) const
{
citerTc it = find(name);
if (it != end() && it->second && value)
{
return it->second->create(value);
}
else
return (B*)NULL;
}
static Factory<B, double>& get()
{
static EngineB instance;
instance.registerEngine();
return instance;
}
private:
virtual B* create(const std::string& name) const { return (B*)NULL; }
private:
virtual void registerEngine();
};
void EngineB::registerEngine()
{
CreatorPtr<B, double>::type BBCreator(new CreatorImpl<B, BB, double>);
registerCreator("BB", BBCreator);
}
#endif
/*<factory.h> ends
/*<main.cpp> begins
#include <class.h>
#include <factory.h>
int main(void)
{
APtr a(EngineA::get().create("AA"));
if (a)
a->print();
double value = 35.7;
BPtr b(EngineB::get().create("BB",&value));
if (b)
b->print();
return 0;
}
/*<main.cpp> ends
The compilation errors are:
....../boost//boost_1_46_1/include/boost/smart_ptr/shared_ptr.hpp: In constructor ‘boost::shared_ptr<T>::shared_ptr(Y*) [with Y = CreatorImpl<B, BB, double>, T = Creator<B, void>]’:
./factory.h:116: instantiated from here
....../boost//boost_1_46_1/include/boost/smart_ptr/shared_ptr.hpp:187: error: cannot convert ‘CreatorImpl<B, BB, double>*’ to ‘Creator<B, void>*’ in initialization
./factory.h: In member function ‘bT* CreatorImpl<bT, cT, pT>::create() [with bT = B, cT = BB, pT = double]’:
main.cpp:15: instantiated from here
./factory.h:27: error: no matching function for call to ‘BB::BB()’
./class.h:36: note: candidates are: BB::BB(double)
./class.h:34: note: BB::BB(const BB&)
./factory.h: In member function ‘bT* CreatorImpl<bT, cT, pT>::create(const pT*) [with bT = B, cT = BB, pT = double]’:
main.cpp:15: instantiated from here
./factory.h:28: error: no matching function for call to ‘BB::BB(const double*&)’
./class.h:36: note: candidates are: BB::BB(double)
./class.h:34: note: BB::BB(const BB&)
./factory.h: In member function ‘bT* CreatorImpl<bT, cT, pT>::create(const pT*) [with bT = A, cT = AA, pT = void]’:
main.cpp:15: instantiated from here
./factory.h:28: error: no matching function for call to ‘AA::AA(const void*&)’
./class.h:18: note: candidates are: AA::AA()
./class.h:18: note: AA::AA(const AA&)
make: *** [test] Error 1
Can anyone help with the errors? Is this a good way to create a generic template based factory?
First error:
typedef boost::shared_ptr< Creator<bT> > type;
You have forgotten to pass pT:
typedef boost::shared_ptr< Creator<bT,pT> > type;
The second:
virtual bT* create(const pT* param) { return new cT(param); }
Either accept a reference in create, or pass the dereferenced pointer to the constructor:
virtual bT* create(const pT& param) { return new cT(param); } // and change the other parts of the code accordingly to accept reference instead of pointer
// or:
virtual bT* create(const pT* param) { return new cT(*param); }
The bigger problem is that in this approach both versions of create is generated for a given cT, and won't compile because of the missing constructor overloads.
Specialize for void, and keep only those overloads of create that make sense. This approach works:
#ifndef INCLUDED_CLASS
#define INCLUDED_CLASS
#include <iostream>
#include <boost/shared_ptr.hpp>
class A
{
public:
A() { _a = 27; }
void print() const { std::cout << "A is " << _a << "." << std::endl; }
protected:
int _a;
};
typedef boost::shared_ptr<A> APtr;
class AA : public A
{
public:
void print() const { std::cout << "AA is " << _a << "!" << std::endl; }
};
class B
{
public:
B(double b) { _b = b; }
void print() const { std::cout << "B is " << _b << "." << std::endl; }
protected:
double _b;
};
typedef boost::shared_ptr<B> BPtr;
class BB : public B
{
public:
BB(double b) : B(b) {};
void print() const { std::cout << "BB is " << _b << "!" << std::endl; }
};
#endif
// ----
#ifndef INCLUDED_FACTORY
#define INCLUDED_FACTORY
#include <map>
#include <string>
#include <boost/shared_ptr.hpp>
template<class bT, class pT = void>
class Creator
{
public:
virtual bT* create(const pT* param) = 0;
};
template<class bT>
class Creator<bT>
{
public:
virtual bT* create() = 0;
};
template <class bT, class pT = void>
struct CreatorPtr
{
typedef boost::shared_ptr< Creator<bT,pT> > type;
};
template <class bT>
struct CreatorPtr<bT>
{
typedef boost::shared_ptr< Creator<bT> > type;
};
template <class bT, class cT, class pT = void>
class CreatorImpl : public Creator<bT, pT>
{
public:
virtual bT* create(const pT* param) { return new cT(*param); }
};
template <class bT, class cT>
class CreatorImpl<bT,cT> : public Creator<bT>
{
public:
virtual bT* create() { return new cT; }
};
template<class CreatorPtrType>
class FactoryBase
{
protected:
FactoryBase() {}
FactoryBase(const FactoryBase&) {}
FactoryBase &operator=(const FactoryBase&) { return *this; }
void registerCreator(const std::string& name, CreatorPtrType creator)
{ _table_creator[name] = creator; }
typedef std::map<std::string, CreatorPtrType> tableCreator;
typedef typename tableCreator::const_iterator citerTc;
citerTc begin() const { return _table_creator.begin(); }
citerTc end() const { return _table_creator.end(); }
citerTc find(const std::string& name) const { return _table_creator.find(name); }
protected:
tableCreator _table_creator;
};
template<class bT, class pT = void>
class Factory : public FactoryBase<typename CreatorPtr<bT, pT>::type>
{
public:
virtual bT* create(const std::string& name, const pT* param) const = 0;
};
template<class bT>
class Factory<bT> : public FactoryBase<typename CreatorPtr<bT>::type>
{
public:
virtual bT* create(const std::string& name) const = 0;
};
class A;
class EngineA : public Factory<A>
{
public:
virtual A* create(const std::string& name) const
{
citerTc it = find(name);
if (it != end() && it->second)
{
return it->second->create();
}
else
return (A*)NULL;
}
static Factory<A>& get()
{
static EngineA instance;
instance.registerEngine();
return instance;
}
private:
virtual void registerEngine();
};
void EngineA::registerEngine()
{
CreatorPtr<A>::type AACreator(new CreatorImpl<A, AA>);
registerCreator("AA", AACreator);
}
class B;
class EngineB : public Factory<B, double>
{
public:
virtual B* create(const std::string& name, const double* value) const
{
citerTc it = find(name);
if (it != end() && it->second && value)
{
return it->second->create(value);
}
else
return (B*)NULL;
}
static Factory<B, double>& get()
{
static EngineB instance;
instance.registerEngine();
return instance;
}
private:
virtual void registerEngine();
};
void EngineB::registerEngine()
{
CreatorPtr<B, double>::type BBCreator(new CreatorImpl<B, BB, double>);
registerCreator("BB", BBCreator);
}
#endif
// ----
#include <class.h>
#include <factory.h>
int main(void)
{
APtr a(EngineA::get().create("AA"));
if (a)
a->print();
double value = 35.7;
BPtr b(EngineB::get().create("BB",&value));
if (b)
b->print();
return 0;
}
Check out my answer here for something similar: https://stackoverflow.com/a/18253631/2288854
The code uses macros to produce a generic factory template which takes up to N parameters. It wont work in c++98, but perhaps it can give you some ideas.

Defining a function template as a callback for a class template

I want to define a class template that takes a callback function of the same type. Something like:
typedef template<class T> bool CallbackFn( T x );
template<class T> class MyClass
{
public:
MyClass() {}
~MyClass() {}
void addCallbackFn( CallbackFn* fn ) { callbackFn = fn; }
private:
CallbackFn* callbackFn;
};
And it would be used like this:
bool testFunctionInt(int x) { return true; }
bool testFunctionString(std::string x) { return true; }
MyClass<int> a;
a.addCallbackFn( testFunctionInt );
MyClass<std::string> b;
b.addCallbackFn( testFunctionString );
Unfortunately the callback function cannot be defined as a function template via the typedef.
Is there another way to do this?
#include <string>
template <typename T>
class MyClass {
public:
typedef bool CallbackFn(T x);
MyClass() : cb_(NULL) {}
~MyClass() {}
void addCallbackFn(CallbackFn *fn) { cb_ = fn; }
private:
CallbackFn *cb_;
};
static bool testFunctionInt(int x) { return true; }
static bool testFunctionString(std::string x) { return true; }
int main()
{
MyClass<int> a;
a.addCallbackFn( testFunctionInt );
MyClass<std::string> b;
b.addCallbackFn( testFunctionString );
}
Move the typedef inside of the class like this:
template<class T> class MyClass
{
public:
MyClass() {}
~MyClass() {}
typedef bool CallbackFn( typename T x );
void addCallbackFn( CallbackFn* fn ) { callbackFn = fn; }
//you could also do this
typedef bool (*CallbackFnPtr)(typename T x);
void addCallbackFnPtr(CallbackFnPtr fn ) { callbackFn = fn; }
private:
CallbackFn* callbackFn; //or CallbackFnPtr callbackFn;
};
I'm assuming you meant MyClass<std::string> b; in your example.
I made some changes.
template<class T>
class MyClass
{
public:
typedef bool (*CallbackFn)( T x );
MyClass() {}
~MyClass() {}
void addCallbackFn( CallbackFn fn ) { callbackFn = fn; }
private:
CallbackFn callbackFn;
};
bool testFunctionInt(int x)
{
return true;
}
int main(int argc, char * argv[])
{
MyClass<int> c;
c.addCallbackFn(testFunctionInt);
return 0;
}