I know it's possible to separate to create a pointer to member function like this
struct K { void func() {} };
typedef void FuncType();
typedef FuncType K::* MemFuncType;
MemFuncType pF = &K::func;
Is there similar way to construct a pointer to a const function? I've tried adding const in various places with no success. I've played around with gcc some and if you do template deduction on something like
template <typename Sig, typename Klass>
void deduce(Sig Klass::*);
It will show Sig with as a function signature with const just tacked on the end. If to do this in code it will complain that you can't have qualifiers on a function type. Seems like it should be possible somehow because the deduction works.
You want this:
typedef void (K::*MemFuncType)() const;
If you want to still base MemFuncType on FuncType, you need to change FuncType:
typedef void FuncType() const;
typedef FuncType K::* MemFuncType;
A slight refinement showing how to do it without a typedef.
In a deduced context like the following, you can't use a typedef.
template <typename Class, typename Field>
Field extract_field(const Class& obj, Field (Class::*getter)() const)
{
return (obj.*getter)();
}
applied to some class with a const getter:
class Foo {
public:
int get_int() const;
};
Foo obj;
int sz = extract_field(obj, &Foo::get_int);
Another more direct way to do it (avoiding using and typedefs) is this:
#include <iostream>
class Object
{
int i_;
public:
int j_;
Object()
: Object(0,0)
{}
Object(int i, int j)
: i_(i),
j_(j)
{}
void printIplusJplusArgConst(int arg) const
{
std::cout << i_ + j_ + arg << '\n';
}
};
int main(void)
{
void (Object::*mpc)(int) const = &Object::printIplusJplusArgConst;
Object o{1,2};
(o.*mpc)(3); // prints 6
return 0;
}
mpc is a const method pointer to Object.
Related
I'm attempting to create a base class that will store signals (in the form of an int) and allow me to later use them to call functions specified by the derived class. They are stored in an unordered_map because it's exactly what I need -- 1 signal = 1 function (plus it's fast).
Though, I'm having some trouble calling them, getting a huge error in the form of:
no match for call to ‘(std::unordered_map<int, std::function<void()>, std::hash<int>, std::equal_to<int>, std::allocator<std::pair<const int, std::function<void()> > > >::mapped_type {aka std::function<void()>}) (int&, int&)’
The compile-error is from signals_[_sig](args...);
const int SIGCHANGE = 1;
template<typename... Args>
class Signal {
private:
std::unordered_map< int, std::function<void(Args...)> > signals_;
inline void SetSignal(const int& _sig, std::function<void(Args...)> _func) {
signals_[_sig] = _func;
}
public:
Signal() {}
~Signal() {}
template<typename... Ts>
void Sig(const int& _sig, Ts... args) {
if (signals_.find(_sig) != signals_.end()) {
signals_[_sig](args...);
}
}
};
class Obj : public Signal<> {
private:
int num_;
public:
Obj* child;
void Change(int _num) {
num_ = _num;
child->Sig(SIGCHANGE, _num);
}
void HandleChanged(int _num) {
num_ = _num;
}
};
int main() {
Obj* obj1 = new Obj();
Obj* obj2 = new Obj();
obj1->child = obj2;
obj1->Change(10);
}
Also, I have no idea if I'm using the templates correctly - it's been ages since I last used them. Should each function have its own template? Why do I have to specify the template before the class if I want to use it for a member variable?
As you function has a single int parameter, you need to have
class Obj : public Signal<int>
instead of
class Obj : public Signal<>
The later creates a map with functions prototyped void(), whereas you need a function prototyped void(int).
Also, templatizing the Sig function is useless, because you will not be able to call it with any other set of parameters than Args anyway. So it can simply be
void Sig(const int& _sig, Args... args) {
if (signals_.find(_sig) != signals_.end()) {
signals_[_sig](args...);
}
}
If your goal is to support storing functions with arbitrary prototype, that does need to be done different way, basically via runtime polymorphism (all the items in the map need to be of the same type, so the type itself would need to do the call polymorphism under the hood).
EDIT
One possibility with function prototypes defined according to the signal type. Requires that the signal ints will always be passed as compile-time constants - the different functor for particular signal types are stored in std::tuple:
const int SIGZERO = 0;
const int SIGCHANGE = 1;
const int SIGOTHER = 2;
// non-specialized template intentionally left empty
// (or can provide default prototype)
template<int SIG>
struct SignalPrototype;
template<>
struct SignalPrototype<SIGZERO>
{
typedef std::function< void() > type;
};
template<>
struct SignalPrototype<SIGCHANGE>
{
typedef std::function< void(int) > type;
};
template<>
struct SignalPrototype<SIGOTHER>
{
typedef std::function< void(int, int) > type;
};
class Signal {
private:
std::tuple<
SignalPrototype<SIGZERO>::type,
SignalPrototype<SIGCHANGE>::type,
SignalPrototype<SIGOTHER>::type
> signals_;
protected:
template<int SIG>
inline void SetSignal(typename SignalPrototype<SIG>::type _func) {
std::get<SIG>(signals_) = _func;
}
public:
template<int SIG, typename... Ts>
void Sig(Ts... args) {
SignalPrototype<SIG>::type func = std::get<SIG>(signals_);
if (func)
func(args...);
}
};
struct MyHandler : SignalPrototype<SIGCHANGE>::type
{
void operator()(int x)
{
std::cout << "Called MyHandler with x = " << x << std::endl;
}
};
class Obj : public Signal {
private:
int num_;
public:
Obj* child;
Obj()
{
SetSignal<SIGCHANGE>(MyHandler());
}
void Change(int _num) {
num_ = _num;
child->Sig<SIGZERO>();
child->Sig<SIGCHANGE>(_num);
child->Sig<SIGOTHER>(1, 2);
}
void HandleChanged(int _num) {
num_ = _num;
}
};
(and in general, it could be actually better for Signal to be member of the Obj instead of inheritance)
I wanted to create a simple template class having a member variable ret. For some reason my MSVC 2010 compiler complains, that there is no declared variable named ret in Converter<double>. I'm really clueless, why?
template<typename M>
struct Converter {
M ret;
void operator()(const int& value) {
throw std::exception("Not implemented!");
}
};
template<>
struct Converter<double> {
void operator()(const int& value) {
ret=value;
}
};
int main() {
Converter<int> x;
}
This is another class (there is no inheritance or any other depenency here):
template<>
struct Converter<double> {
double ret;
void operator()(const int& value) {
ret=value;
}
};
I know this is already marked solved, but I thought I should just clarify this further.
Converter<double> and Converter<int> are different separate classes, so ret would not be defined in your double variation until you declare it as one of its members.
Regardless, it appears what you're trying to achieve is inheritance, which can be done in a similar way:
template<typename M>
struct AbstractConverter { // you could call it 'Converter' too, and it'll work as you expect
M ret;
virtual void operator()(const int& value) {
throw std::exception("Not implemented!");
}
//or
virtual void operator(const int &value) = 0; //pure virtual
// will not compile if someone wants to use it directly
};
template<>
struct Converter<double> : public AbstractConverter<double>{
void operator()(const int& value) { // we implement the operator here
ret=value;
}
};
I'll paste the relevant code only
Template class:
template<class TMsgType, class TKeyType>
struct mapped_subscription_handler
{
protected:
typedef std::function<void(TKeyType const &, TMsgType*)> handler_t;
typedef std::unordered_multimap<TKeyType, subscr_obj<handler_t>> map_t;
public:
void call(TKeyType const & key, TMsgType* msg)
{
//blah
}
public:
handler_id_t register_handler(TKeyType const & key, handler_t handler)
{
//blah
}
void unregister_handler(TKeyType key, handler_id_t id)
{
//blah
}
private:
map_t _map;
};
Implementation class:
typedef clients::mapped_subscription_handler<NS_Snap::NS_MD::DepSnapshot, clients::header_info<NS_Snap::NS_DEF::Header>::mdid_t> depth_handler_t;
typedef clients::mapped_subscription_handler<NS_Snap::NS_MD::TrdSnapshot, clients::header_info<NS_Snap::NS_DEF::Header>::mdid_t> trd_handler_t;
class data_client
:public depth_handler_t,
public trd_handler_t
{
public:
data_client(const std::string & host, int port);
virtual ~data_client();
clients::handler_id_t register_on_connect(std::function<void()> connect_handler);
using depth_handler_t::register_handler;
using trd_handler_t::register_handler;
using depth_handler_t::unregister_handler;
using trd_handler_t::unregister_handler;
};
Usage:
class time_comparer
{
internal_clients::data_client *_int_client;
void whenever()
{
//Compiler complains about ambiguous call here.
_int_client->register_handler(rep->GetId(), boost::bind(&time_comparer::on_internal_depth, this, _1, _2));
}
void on_internal_depth(uint64_t const & key, NS_Snap::NS_MD::DepSnapshot* depth)
{
//blah
}
};
The compiler complains of ambiguous reference when I call register_handler. Shouldn't it be able to identify which register_handler I am calling (based on boost::bind type)? Otherwise I have to qualify the call with the class name which is ugly.
EDIT:
Based on input from Sebastian Redl
This simpler example encounters the same problem
#include <iostream>
#include <functional>
template<class T>
struct test_template
{
template<class TArg>
void do_(T t, TArg arg)
{
t(arg);
}
};
class test_class :
public test_template<std::function<void(char*)>>,
public test_template<std::function<void(int)>>
{
public:
using test_template<std::function<void(char*)>>::do_;
using test_template<std::function<void(int)>>::do_;
};
int main()
{
test_class tc;
tc.do_([](int x){std::cout << x << std::endl; }, 10);
tc.do_([](char* x) {std::cout << x << std::endl; }, "what");
return 0;
}
Is there any way around this without explicitly specifying the overload when calling? i.e.
tc.test_template<std::function<void(int)>>::do_([](int x){std::cout << x << std::endl; }, 10);
In the simplified example, you may use SFINAE to remove template based mostly on the non function argument.
template<class T>
struct test_template
{
template<class TArg>
auto do_(T t, TArg arg)
-> decltype(t(arg), void())
{
t(arg);
}
};
Live demo
std::function is very liberal in conversions to it, and in particular the standard doesn't require the conversion to be SFINAEd out if the passed function object isn't compatible. So both function types appear to be constructable from the binds, which is why you get an ambiguity.
I've got a class D, that I want to have classes A,B,C inherit from. However, the functions that I want to declare as pure virtual are templated.
Unfortunately, in the words of visual studio:
member function templates cannot be virtual
Classes A,B,C have a member operator called in the exact same manner, though may return different values (double or unsigned int namely. But I'd be happy to get it to work with just double):
template<typename T>
double operator()(T&, unsigned int b){/*code*/};
How could I properly create a polymorphic collection of classes A,B,C (similar to a std::vector<D*> that would work if I didn't want member function templates) that does what I'm trying to do?
EDIT:
An example of what I'd like to be able to do:
std::default_random_engine rng((unsigned int) std::time(0));
std::vector<D*> v;
v.push_back(new A(0.3));
v.push_back(new B(1.0,3.2));
v.push_back(new C);
for(auto x : v){
for(auto y : x->operator()(rng,5){
std::cout << y << ',';
}
std::cout << std::endl;
}
I'm not entirely sure what you want to do, but if you move the template definition to the class instead of the method, everything is happy. Does that do what you want?
template<typename T>
class A
{
public :
virtual double operator() (T& t, unsigned int b) = 0;
};
template<typename T>
class B : public A<T>
{
public:
virtual double operator() (T& t, unsigned int b)
{
// code
}
};
EDIT:
Or, given that you don't want the template at the class level, what about moving the random calculation out of the polymorphic method, and then having a simple plymorphic method for the actual hard part. This assumes you only want to generate one random number, If you want more, you could always create a vector of random numbers, the size of which is determined in construction. Anyway the code below demonstrates what I am talking about:
class D
{
public :
template<typename T>
double operator() (T& t, unsigned int b)
{
double calc_rand = t();
return DoStuff(calc_rand, b);
}
protected :
virtual double DoStuff(double rnd_value, unsigned int b) = 0;
};
class A : public D
{
protected :
virtual double DoStuff(double rnd_value, unsigned int b)
{
return rnd_value * b;
}
};
int main(void)
{
std::random_device rd;
A a;
std::cout << a(rd, 5) << std::endl;
}
You'll most probably need to use delegates here. If all the classes have the same name and parameters, it's as easy as doing:
template <typename T>
class baseWrapper{
double method(T& a, unsigned int b) = 0;
};
template <typename T, typename myClass>
class wrapper: public baseWrapper<T>{
myClass &instance;
double method(T& a, unsigned int b){
return instance.method<T>(a,b);
};
wrapper(myClass &instance){this->instance = instance;};
};
And then you can create a collection of delegates:
std::vector<baseWrapper<int>*> vec;
A myObject1, B myObject2;
wrapper<int,A> wrapper1(myObject1);
wrapper<int,B> wrapper2(myObject2);
vec.push_back(&wrapper1);
vec.push_back(&wrapper2);
If the functions are named differently, you'll need to pass a function pointer as an additional parameter, or test it with SFINAE.
Perhaps you can implement a type erasure for the template parameter of the member functions. Going with your RNG example:
class RandUIntIfc {
public:
virtual ~RandUIntIfc() = 0;
virtual unsigned int min() const = 0;
virtual unsigned int max() const = 0;
virtual unsigned int operator()() = 0;
};
class RandUInt {
public:
template <typename RNG>
explicit RandUInt(RNG& rng);
unsigned int min() const;
unsigned int max() const;
unsigned int operator()();
private:
std::shared_ptr<RandUIntIfc> impl_;
template <typename RNG>
class Impl : public RandUIntIfc {
public:
explicit Impl(RNG& rng);
virtual unsigned int min() const;
virtual unsigned int max() const;
virtual unsigned int operator()();
private:
RNG& ref_;
};
};
I hope all the actual member definitions are obvious. That leaves just the change to D and code that uses it:
class D {
public:
virtual ~D() = 0;
virtual double operator()(RandUInt rng, unsigned int b) = 0;
};
std::default_random_engine rng((unsigned int) std::time(0));
RandUInt typeless_rng(rng);
std::vector<D*> v;
// ...
for(auto x : v){
for(auto y : x->operator()(typeless_rng,5){
std::cout << y << ',';
}
std::cout << std::endl;
}
You shouldn't use a template function but just pass delegate to the rng through the virtual function. So basically you could do this:
class D
{
virtual double operator()(std::function<int()>, int)=0;
};
And call it like this:
std::default_random_engine rng;
std::vector<D*> v;
...
for(auto x : v)
{
std::cout << x->operator(std::bind(rng), 5) << ',';
}
I have two methods f(vector<int>& x, ....) and g(DBConn& x, ....)
where the (....) parameters are all identical.
The code inside the two methods are completely identical except for one statement
where we do different actions based on the type of x:
in f(): we do x.push_back(i)
in g(): we do x.DeleteRow(i)
What is the simplest way to extract the common code into one method and yet
have the two different statements?
I am thinking of having a templated functor that overloads operator () (int a) but that seems overkill.
common_function(....)
{
}
f(vector<int>x,... )
{
x.push_back(i);
common_f(...);
}
g(DBConn& x, ....)
{
x.DeleteRow(i);
common_f(...);
}
You could write a simple adapter with two implementations, each calling the desired method of a different class.
class MyInterface {
public:
virtual doIt(int i) = 0;
}
class VectorImp : public MyInterface {
public:
vector<int>& v;
VectorImp(vector<int>& theVector) : v(theVector) {}
doIt(int i) { x.push_back(i); }
}
class DbImp : public MyInterface {
public:
DBConn& c;
VectorImp(DBConn& conn) : c(conn) {}
doIt(int i) { c.DeleteRow(i); }
}
template<class T>
struct Adapter;
template<>
struct Adapter<vector<int> >
{
static void execute(vector<int> &x, int i)
{
x.push_back(i);
}
};
template<>
struct Adapter<DBConn>
{
static void execute(DBConn &x, int i)
{
v.DeleteRow(i);
}
};
template<class T>
void f(T &t, ...)
{
...
Adapter<T>::execute(t, i);
...
}
OR:
template<class T>
struct adapter_traits;
template<>
struct adapter_traits<vector<int> >
{
typedef void (vector<int>::*PMF)(int);
static const PMF pmf = &vector<int>::push_back;
}
template<>
struct adapter_traits<DBConn>
{
typedef void (DBConn::*PMF)(int);
static const PMF pmf = &DBConn::DeleteRow;
}
template<class T>
void f(T &t, ...)
{
...
(t.*adapter_traits<T>::pmf)(i);
...
}
NOTE: I might have some syntax wrong but you get the idea.
Yet another idea:
template<class T>
void f(T &t, void (T::*p)(int), ...)
{
...
(t.*p)(i);
}
void g()
{
DBConn x;
vector<int> y;
f(x, &DBConn::DeleteRow, ...);
f(y, &vector<int>::push_back, ...);
}
Classic case for a functor:
#include <vector>
#include <DBConn.h>
// T: The type of the object that is to be manipulated.
// A: The type of the object that will do the manipulating
// This may be a functor object or a function pointer.
//
// As this is a template function the template parameters will
// be deduced by the compiler at compile time.
template<typename T,typename A>
void action(T& obj,A const& action/*,....*/)
{
// Do Stuff
action(obj,5);
// Do more Stuff
}
// Functor object
struct MyVectorAction
{
// Just defines the operator()
// Make sure it is a const method.
// This does the unique bit of code. The parameters should be what you pass into action
void operator()(std::vector<int>& data,int val) const {data.push_back(val);}
};
void f(std::vector<int>& x)
{
action(x,MyVectorAction()/*.... Params ....*/);
}
struct MyDBConnAction
{ void operator()(DBConn& data,int val) const {data.DeleteRow(val);} };
void g(DBConn& x)
{
action(x, MyDBConnAction());
}
int main()
{
std::vector<int> x;
f(x);
}
You could make a function that has the parameters of what you call (...), and this function can implement the logic that is the same in f() and g(). You could then change the implementation of f() and g() to call this new function instead of duplicating the logic. Be careful though if you're doing something duplicated before and after your unique lines. You may need two functions in that case. At any rate I think this would be preferable to having duplicated blocks of code.