Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I want to "store member function in my class" in order to call it later in some cases. But I can't fix my code for storing member functions with parameters. Heres is my code:
class IMemFn
{
public:
IMemFn() {}
IMemFn(const IMemFn& other) = delete;
IMemFn& operator=(const IMemFn& other) = delete;
IMemFn(IMemFn&& other) = delete;
IMemFn& operator=(IMemFn&& other) = delete;
virtual ~IMemFn() {}
virtual void func(const std::string& name, const std::string& value) = 0;
};
template<typename ReturnType, class Class>
class MemFn final : public IMemFn
{
public:
typedef ReturnType(Class::*Method)();
MemFn(Class* object, Method method) : IMemFn(), m_object(object), m_method(method) {};
virtual void func(const std::string& name, const std::string& value) override final
{
(m_object->*m_method)(name, value);
};
private:
Class* m_object;
Method m_method;
};
class Test
{
public:
template <class Class, typename Method>
void addMemFn(Class* obj, Method method) {
auto memFn = new MemFn<typename std::result_of<decltype(method)(Class)>::type, Class>(std::forward<Class*>(obj), std::forward<Method>(method));
m_memFns.push_back(memFn);
}
private:
std::list<IMemFn*> m_memFns;
};
class SomeClass
{
public:
void funcAll(const std::string& name, const std::string& value) { std::cout << "SomeClass func"; }
};
class SomeClass2
{
public:
void func2(const std::string& name, const std::string& value) { std::cout << "SomeClass2 func"; }
};
int main()
{
Test test;
SomeClass someClass;
SomeClass2 someClass2;
test.addMemFn(&someClass, &SomeClass ::funcAll);
test.addMemFn(&someClass2, &SomeClass2::func2);
return 0;
}
But compilation fails with this message: 'type': is not a member of 'std::result_of<Method (Class)>
and in this line: (m_object->*m_method)(name, value);
But if I try to save member function without parameters, then this error doesn't appear.
Thanks for any help!
Several changes required here to make it compile:
Firstly std::result_of<decltype(method)(Class) needs to be std::result_of<Method(Class*,std::string,std::string)
because it is a member function taking a pointer to this plus two arguments.
It looks like function inform in MemFn should be renamed func.
Method needs to be added as a template argument of MemFn.
Then you can invoke the member functions through the test object, for example:
(*test.m_memFns.begin())->func("a", "b");
However you will not be able to return different types from these member functions while also satisfying the interface void IMemFn::func(...).
Thank's everybody for your answers! Seems I'm very tired 'cause of these damn tamplates. I used std::functions with std::bind and everything now is simple and light. So, my final code is:
class Test
{
public:
template <class Class, typename Method>
void addMemFn(Class* obj, Method method) {
auto func = std::bind(method, obj, std::placeholders::_1, std::placeholders::_2);
m_funcs.push_back(func);
}
private:
std::list<std::function<void(const std::string&, const std::string&)>> m_funcs;
};
class SomeClass
{
public:
void funcAll(const std::string& name, const std::string& value) { std::cout << "SomeClass func"; }
};
class SomeClass2
{
public:
void func2(const std::string& name, const std::string& value) { std::cout << "SomeClass2 func"; }
};
int main()
{
Test test;
SomeClass someClass;
SomeClass2 someClass2;
test.addMemFn(&someClass, &SomeClass::funcAll);
test.addMemFn(&someClass2, &SomeClass2::func2);
return 0;
}
Related
This question already has answers here:
What is a dangling reference? [duplicate]
(1 answer)
What is a dangling pointer?
(7 answers)
Closed 5 days ago.
I've been going over my code and fiddling but I can't seem to figure out why I'm not getting the expected output but instead random symbols.
The expected output is: JoeUPSReminderPick up your package!
54.23
I get the < but anything after that is gibberish. Any help would be appreciated.
#include <cstddef> // for std::size_t
#include <iostream>
#include <memory>
#include <ostream>
#include <string>
#include <utility> // for std::move, std::forward
#include <vector>
class xml_node_base
{
public:
virtual ~xml_node_base() = default;
void output(std::ostream& os) const
{
do_output_open(os);
do_output_body(os);
do_output_close(os);
}
protected:
virtual void do_output_open(std::ostream& os) const = 0; // abstract
virtual void do_output_body(std::ostream&) const { } // not abstract
virtual void do_output_close(std::ostream& os) const = 0; // abstract
};
using xml_node_base_t = std::shared_ptr<xml_node_base>;
using xml_node_bases_t = std::vector<xml_node_base_t>;
template <typename T, typename... Args>
inline xml_node_base_t make_xml_node(Args&&... args)
{
return std::make_shared<T>(std::forward<Args>(args)...);
}
class xml_node: virtual public xml_node_base
{
private:
std::string const& node_name;
public:
xml_node() = delete;
xml_node(std::string const& name) : node_name(name)
{
};
protected:
void do_output_open(std::ostream& os) const override
{
os << "<" << node_name << ">";
};
void do_output_close(std::ostream& os) const override
{
os << "</" << node_name << ">";
};
};
class xml_node_with_children: public xml_node
{
private:
xml_node_bases_t children_;
public:
xml_node_with_children() = delete;
xml_node_with_children(std::string const& name) : xml_node(name)
{
};
xml_node_with_children(std::string const& name, std::size_t reserve) : xml_node_with_children(name)
{
children_.reserve(reserve);
};
xml_node_with_children(std::string const& name, xml_node_bases_t children) : xml_node(name), children_(std::move(children))
{
};
protected:
auto& children() { return children_; };
auto const& children() const { return children_; };
void do_output_body(std::ostream& os) const
{
for (auto const& c : children_)
{
c -> output(os);
}
};
};
template <typename T>
class value_node : public xml_node
{
private:
T datum;
protected:
void do_output_body(std::ostream& os) const
{
os << datum;
}
public:
value_node(std::string const& name, T const& v) : xml_node(name), datum(v)
{
}
};
class note : public xml_node_with_children
{
public:
note() = delete;
note(std::string const& to, std::string const& from, std::string const& subject, std::string const& message) : xml_node_with_children("note", 4)
{
children().push_back(make_xml_node<value_node<std::string>>("to",to));
children().push_back(make_xml_node<value_node<std::string>>("from",from));
children().push_back(make_xml_node<value_node<std::string>>("subject",subject));
children().push_back(make_xml_node<value_node<std::string>>("message",message));
}
};
class root : protected xml_node_with_children
{
public:
using xml_node_with_children::xml_node_with_children;
using xml_node_with_children::output;
using xml_node_with_children::children;
};
std::ostream& operator<<(std::ostream& os, root const& r)
{
r.output(os);
return os;
}
int main()
{
root notes{"notes"};
notes.children().push_back(
make_xml_node<note>("Joe", "UPS", "Reminder", "Pick up your package!")
);
notes.children().push_back(
make_xml_node<value_node<double>>("priority",54.23)
);
std::cout << notes << '\n';
}
I think the problem could be with the for loop on line 90, since I'm not too familiar with the -> operator.
std::string const& node_name;
xml_node(std::string const& name) : node_name(name)
This class member is a reference, and the constructor initializes it from a reference that gets passed in as a parameter to the constructor.
Let's trace things all the way back and see where the parameter, to the constructor, originally comes from. Here's one example:
children().push_back(make_xml_node<value_node<std::string>>("to",to));
The parameter is a literal string, "to".
C++ is very famous, and is very well known for giving everyone every opportunity to shoot themself in the foot, if that's what they really want to do, so:
A temporary std::string object gets constructed.
A reference to this object gets passed as a parameter, through several onion layers of constructors, elephant-style.
A reference to this object gets saved in a member of the base class.
After all the constructors finish, and this statement finishes executing, the temporary std::string object, that owns this "to" gets destroyed.
The instance of the class now has a reference to a destroyed object, in its node_name.
This is repeated for all the other objects in the shown code that get constructed like that.
You just shot yourself in the foot.
Suppose I have a class in C++11 like this:
class Something
{
...
private:
class1* a;
class2* b;
class3* c;
public:
class1* reada() { return a; }
class2* readb() { return b; }
class3* readc() { return c; }
void customFunctionForclass1();
void customFunctionForclass2();
void customFunctionForclass3();
}
}
I'd like to make the read functions templated so that if another programmer adds another member class, the corresponding read function will be template-magic created.
Something like this maybe?
class Something
{
...
private:
templateContainer = {class1*,class2*,class3*}
template<thing in templateContainer>
thing variableOfTypeThing;
public:
template<thing in templateContainer>
<thing> read() {return variableOfTypeThing<thing>;}
void customFunctionForclass1();
void customFunctionForclass2();
void customFunctionForclass3();
}
As you can tell from the example, I'm confused.
Basically, I have a class which acts as a container for guaranteed unique class variables (no class1 A; class1 B)
Some function groups for the class are almost identical some function groups are highly varied. It would be great for future people to only have to modify the different parts of the class and get the rest from the templates.
I thought maybe there would be a way by splitting this class up into lots of classes and stuffing them into an array of void pointers, but that seems unwise.
Suggestions?
I'd like to make the read functions templated so that if another programmer adds another member class, the corresponding read function will be template-magic created.
You could encapsulate the user defined classes in a thin wrapper class with a read() function that returns the contained instance. Adding a user defined class to Something would then be done by inheriting wrapper<user_defined_class>.
Basically, I have a class which acts as a container for guaranteed unique class variables
Inheriting this wrapper prevents you from including the same class twice so it could possibly be a way forward:
#include <iostream>
// the "thing" wrapper
template<typename T>
struct thing {
// forward construction arguments to the contained variable
template<class... Args>
thing(Args&&... args) : variable(std::forward<Args>(args)...) {}
// basic interface, const and non-const. I called it get() instead of read()
T const& get() const { return variable; }
T& get() { return variable; }
private:
T variable;
};
// a troublesome user defined class that is not default constructibe :-(
struct user_defined {
user_defined() = delete; // silly example really, but it's just to demonstrate
user_defined(const std::string& v) : str(v) {}
user_defined& operator=(const std::string& v) {
str = v;
return *this;
}
std::string const& say() const { return str; }
private:
std::string str;
};
std::ostream& operator<<(std::ostream& os, const user_defined& ud) {
return os << ud.say();
}
// ... and the "Something" class that inherits the wrapped types.
class Something : thing<int>,
thing<double>,
thing<user_defined>
{
public:
// add initial values for types that are not default constructible
Something(const std::string& val) : thing<user_defined>(val) {}
Something() : Something("") {} // default ctor
// access via derived class, const and non-const
template<typename T>
T const& get() const {
return thing<T>::get(); // get() from the correct base
}
template<typename T>
T& get() {
return thing<T>::get(); // get() from the correct base
}
};
void print(const Something& s) {
// using the const interface
std::cout << s.get<int>() << "\n";
std::cout << s.get<double>() << "\n";
std::cout << s.get<user_defined>() << "\n";
}
int main() {
Something foo;
// using the non-const interface to set
foo.get<int>() = 10;
foo.get<double>() = 3.14159;
foo.get<user_defined>() = "Hello world";
print(foo);
}
Edit: It doesn't fulfill the index part of your question though. You access it using the type you'd like to get() as a tag. You basically build a very rudimentary tuple I guess.
Code based on #Ted Lyngmo's answer:
#include <iostream>
#include <string>
template<typename T>
struct thing {
// forward construction arguments to the contained variable
template<class... Args>
thing(Args&&... args) : variable(std::forward<Args>(args)...) {}
// basic interface, const and non-const. I called it get() instead of read()
T const& get() const { return variable; }
T& get() { return variable; }
protected:
T variable;
};
template<typename ...Ts>
struct things : thing<Ts>... {
template<class... SubTs>
things(thing<SubTs>&&... ts) : thing<SubTs>(std::move(ts))... {}
// access via derived class, const and non-const
template<typename T>
T const& get() const {
return thing<T>::get(); // get() from the correct base
}
template<typename T>
T& get() {
return thing<T>::get(); // get() from the correct base
}
};
// a troublesome user defined class that is not default constructibe :-(
struct user_defined {
user_defined() = delete; // silly example really, but it's just to demonstrate
user_defined(const std::string& v) : str(v) {}
user_defined& operator=(const std::string& v) {
str = v;
return *this;
}
std::string const& say() const { return str; }
private:
std::string str;
};
struct non_default {
non_default() = delete;
non_default(int) {}
};
std::ostream& operator<<(std::ostream& os, const user_defined& ud) {
return os << ud.say();
}
// ... and the "Something" class that inherits the wrapped types.
class Something : public things<int, double, user_defined, non_default>
{
public:
// add initial values for types that are not default constructible
Something(const std::string& val) : things(thing<user_defined>(val), thing<non_default>(0)) {}
Something() : Something("") {} // default ctor
};
void print(const Something& s) {
// using the const interface
std::cout << s.get<int>() << "\n";
std::cout << s.get<double>() << "\n";
std::cout << s.get<user_defined>() << "\n";
}
int main() {
Something foo;
// using the non-const interface to set
foo.get<int>() = 10;
foo.get<double>() = 3.14159;
foo.get<user_defined>() = "Hello world";
print(foo);
}
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've been assigned the following template:
#include <map>
template <typename T>
class Catalog {
struct Item {
//..
};
std::map<int, Item*> items;
public:
Catalog(void);
Catalog(const Catalog&);
~Catalog(void);
bool IsEmpty(void) const;
int Size() const;
void Add(T*);
T* Remove(T*);
T* Find(T*);
typedef void (T::*pFunc) (const T&);
void Inspection(pFunc) const;
};
Next, there is an abstract Product class and three subclasses:
class Product {
protected:
unsigned int _id;
string _name;
public:
Product(const int& id, const string& name) : _id(id), _name(name) {};
virtual void Action(const Product& p) = 0;
virtual int hashCode() {
return _id*100;
};
unsigned int getId(void) const {return _id;};
string getName(void) const {return _name;};
};
class ProductA : public Product {
public:
ProductA(const int& id, const string& name) : Product(id, name) {};
virtual void Action(const Product& p) {
cout << "ahoj" << endl;
};
};
Finally, class ProductsCatalog that handles a Catalog instance:
class ProductsCatalog {
Catalog<Product> catalog;
public:
//..
void CatalogInspection(void) const {
catalog.Inspection(&Product::Action);
}
};
What I have trouble with is the Inspection method:
template <typename T> void Catalog<T>::Inspection(pFunc p) const {
for (std::map<int, Item*>::const_iterator it=items.begin(); it!=items.end(); ++it) {
it->second->Product->*p(*(it->second->Product));
}
};
I am getting the following error:
error C2064: term does not evaluate to a function taking 1 arguments
I've tried everything I could think of, without success. The following works as intended, but is obviously not abstract enough:
it->second->Product->Action(*it->second->Product);
Did you try
(it->second->Product->*p)(*(it->second->Product));
for calling the method?
The thread Calling C++ class methods via a function pointer seems to be related.
I am trying to create template classes for some repetitive functions that will be required for sending data around, of different types. However, my issue (I think) is really with InterfacePublisher::addSubscription() function that is utilizing boost::signals2::signal::connect().
It seems like connect function is taking the location of the base classes, even though derived classes override them. I am sure there is going to be a fix for this but am stuck with it for a long while now.
I am pasting my code below. The idea is to pass a string from StringPublisher to StringSubscriber without hard-coding the class names through the templates:
#include <string>
#include <iostream>
#include <boost/lambda/lambda.hpp>
#include <boost/signals2/signal.hpp>
#include <boost/signals2/signal_base.hpp>
#include <boost/signals2/slot.hpp>
#include <boost/signals2/slot_base.hpp>
template <class T>
class InterfaceSubscriber
{
public:
InterfaceSubscriber(const std::string& name)
: mName (name) {}
virtual void onData (const std::string& source, T& data)
{
std::cout << "InterfaceSubscriber::onData::BASE SHOULD BE IGNORED\n";
}
protected:
const std::string mName;
};
template <class T>
class InterfacePublisher
{
public:
InterfacePublisher(const std::string& publisherName)
: mPublisherName (publisherName)
{
}
void publish(T& data)
{
mSignalArgs(mPublisherName, data);
}
void addSubscription (InterfaceSubscriber<T>* subsc)
{
// The section where I think problem is. There is where the solution should be
mSignalArgs.connect( std::bind (InterfaceSubscriber<T>::onData , *subsc, std::placeholders::_1, std::placeholders::_2) );
}
protected:
boost::signals2::signal<void (const std::string& publisherName, T& data)> mSignalArgs;
const std::string mPublisherName;
};
class StringSubscriber : public InterfaceSubscriber<std::string>
{
public:
StringSubscriber (const std::string& subscName) : InterfaceSubscriber(subscName) {}
void onData (const std::string& source, std::string& data) override
{
std::cout << mName << ":[" << source << "]Received string of value: " << data << std::endl;
}
};
class StringPublisher : public InterfacePublisher<std::string>
{
public:
StringPublisher (const std::string& name) : InterfacePublisher(name) {}
};
int main()
{
StringSubscriber subscriber1("String_Subscriber_1");
StringSubscriber subscriber2("String_Subscriber_2");
StringPublisher publisher("Publisher_Of_String");
publisher.addSubscription(&subscriber1);
publisher.addSubscription(&subscriber2);
std::string str = "Hello World";
// This should lead to StringSubscriber::onData being called, but instead ends up calling InterfaceSubscriber<T>::onData
publisher.publish(str);
}
StringSubscriber is being sliced during the construction of the std::bind functor, resulting in InterfaceSubscriber<T>::onData() executing on an object with a runtime type of InterfaceSubscriber<T> rather than the runtime type of the object provided to InterfacePublisher<T>::addSubscription().
void addSubscription(InterfaceSubscriber<T>* subsc)
{
mSignalArgs.connect(std::bind(&InterfaceSubscriber<T>::onData,
*subsc, ...);
// ^~~ sliced
}
To resolve this, either pass the pointer directly or pass a std::ref object as the instance.
void addSubscription(InterfaceSubscriber<T>* subsc)
{
mSignalArgs.connect(std::bind(&InterfaceSubscriber<T>::onData,
subsc, ...);
// ^~~ pointer
}
or
void addSubscription(InterfaceSubscriber<T>* subsc)
{
mSignalArgs.connect(std::bind(&InterfaceSubscriber<T>::onData,
std::ref(*subsc), ...);
// ^~~ reference
}