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.
Related
I was trying to figure out this exercise from a school exam.
They implemented an abstract template Book class, and the assignment is to implement a bookshelf class.
I tried to construct a set of book pointers with a custom comparator, but then I encounter a compilation error:
In template: reference to type 'const Book<std::basic_string<char>>' could not bind to an lvalue of type 'const std::_Rb_tree<...>
(I implemented a sub class BOOK2 just for debugging purposes)
This is the long given book abstract class
#include <iostream>
#include <set>
#include <string>
#include <utility>
template <class T>
class Book
{
// any member variables are inaccessible to descendants
private:
std::string _title; // do not call a copy-ctr
T _author; // do not call a copy-ctr
size_t _number_of_pages;
public:
Book(std::string title,
T author,
size_t number_of_pages)
: _title(std::move(title)),
_author(std::move(author)),
_number_of_pages(number_of_pages)
{}
virtual ~Book() = default;
const std::string& get_title() const
{ return _title; }
const T& get_author() const
{ return _author; }
size_t get_number_of_pages() const
{ return _number_of_pages; }
public:
virtual Book<T>* clone() const = 0; // implemented *only* by descendent classes
virtual bool is_available_on(const std::string& platform) const = 0; // implemented *only* by descendant classes
protected:
virtual void do_output(std::ostream& os) const // can be overridden; can be accessed *only* by descendants
{
os << _title << ", " << _author << ", " << _number_of_pages << " pages";
}
// output should depend on who book really is
friend std::ostream& operator<<(std::ostream& os, const Book& book)
{
book.do_output(os);
return os;
}
};
This is what I implemented:
class Book2: public Book<std::string>{
public:
Book2(std::string &title,
std::string &author,
size_t number_of_pages)
: Book<std::string>(title,author,number_of_pages){}
bool is_available_on(const std::string &platform) const override{return
true;}
Book<std::basic_string<char>> * clone() const override{
Book<std::basic_string<char>> * a{};
return a;
}
};
template<class TP>
static bool book_comp(const Book<TP>& a,const Book<TP> & b){
return a.get_title()<b.get_title();}
template<class TT>
class Bookshelf
{
public:
typedef bool(*book_comp_t)(const Book<TT>& a,const Book<TT> & b);
// DO NOT CHANGE NEXT TWO LINES:
auto& get_books() { return _books; } // DO NO CHANGE
auto& get_books() const { return _books; } // DO NO CHANGE
Bookshelf():_books(book_comp<TT>){}
void add(Book<TT>& book)
{
size_t init_size=_books.size();
_books.insert (&book);
if(init_size==_books.size()){
throw std::invalid_argument("book already in bookshlf");
}
}
// sorted lexicographically by title
friend std::ostream& operator<<(std::ostream& os, const Bookshelf<TT>&
bookshelf)
{
for(const auto& book :bookshelf._books)
{
os << *book << std::endl;
}
}
private:
std::set<Book<TT>*,book_comp_t> _books;
};
int main ()
{
std::string a ="aba";
std::string bb ="ima;";
Book2 b = Book2(a, bb, 30);
Bookshelf<std::string> shelf;
std::cout<<b;
shelf.add(b);
}
I tried changing the const qualifiers in some places, and it didn't work.
I also tried without using the custom comparator function which worked ok.
I think this is probably some syntax error maybe?
std::set<Book<TT>*,book_comp_t> _books; is a set of Book<TT>*, and thus requires a comparator whose parameters are of type Book<TT>*, not const Book<TT>&
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);
}
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;
}
Assume I have a base class like this:
template<typename T>
class Base {
public:
Base& operator()(const T& value) {
this->value = value;
return *this;
}
T value;
};
Now I want to inherit from this class to create type-specific classes
class InheritedFloat : public Base<float> {} inheritedFloat;
Now here I try to catch this inheritance in a functon:
void function(const InheritedFloat& inherited) {
std::cout << inherited.value << '\n';
}
Calling this function like this works fine, of course:
int main() {
function(inheritedFloat); //(inheritedFloat is a global instance)
return 0;
}
But when I try to call it with the operator()(const float& value){...} member function, function(const InheritedFloat& inherited){...} doesn't see it as a InheritedFloat-Type but instead as a Base<float>-Type:
int main() {
function(inheritedFloat(10.f)); //error
return 0;
}
Error:
Error C2664 'void function(const InheritedFloat &)': cannot convert argument 1 from 'Base<float>' to 'const InheritedFloat &'
So how can I make operator()(const T& value){...} return InheritedFloat& instead of Base<float>&?
To clearify further, this is just a simplified example (of course). I have dozens of inheritance cases. So I can't just template-specify function()
template<typename T>
void function(const Base<T>& inherited) {
std::cout << inherited.value << '\n';
}
because each inheritance needs to be treated differently. Types will overlap, so there will be multiple Base<std::size_t> cases, for example.
The whole code:
#include <iostream>
template<typename T>
class Base {
public:
Base& operator()(const T& value) {
this->value = value;
return *this;
}
T value;
};
class InheritedFloat : public Base<float> {} inheritedFloat;
void function(const InheritedFloat& inherited) {
std::cout << inherited.value << '\n';
}
int main() {
function(inheritedFloat(10.f));
return 0;
}
Thanks for reading, I appreciate any help!
You can utilize CRTP here. By supplying extra template parameter you can make base class function return a reference to a derived class:
#include <iostream>
template<typename Derived, typename T>
class Base {
public:
Derived & operator()(const T& value) {
this->value = value;
return *static_cast<Derived *>(this);
}
T value;
};
class InheritedFloat : public Base<InheritedFloat, float> {} inheritedFloat;
void function(const InheritedFloat& inherited) {
std::cout << inherited.value << '\n';
}
int main() {
function(inheritedFloat(10.f));
return 0;
}
online compiler
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
}