How to clear the std::map<K,V*> container and delete all the pointed objects safely? - stdmap

None of the standard library containers will call delete on contained raw pointers. I have checked for a solution on SO for C++98 but have not found the answer.
I have created template <typename K, typename V> void clearAndDestroy( std::map<K, V*> *&myMap) as a replacement function for std::clear() (remove all elements and call the destructors).
It works for maps with pointers to objects std::map(key,V*). The function works also for cases when map contains same V* pointers for the different keys.
#include <iostream>
#include <map>
#include <string>
#include <set>
using namespace std;
// clearAndDestroy deletes all objects and remove them from the std::map(K,V*) container.
template <typename K, typename V>
void clearAndDestroy( std::map<K, V*> *&myMap)
{
if(myMap == NULL)
return;
std::set<V*> mySet;
typename std::map<K,V*>::iterator itr;
typename std::set<V*>::iterator sitr;
itr = myMap->begin();
while (itr != myMap->end()) {
mySet.insert(itr->second);
++itr;
}
sitr = mySet.begin();
while (sitr != mySet.end()) {
delete(*sitr);
++sitr;
}
myMap->clear();
}
template <typename K, typename V> void clear1( std::map<K, V*> *myMap)
{
if(myMap == NULL) return;
typename std::map<K, V*>::iterator itr = myMap->begin();
while (itr != myMap->end()) {
typename std::map<K, V*>::iterator toErase = itr;
++itr;
myMap->erase(toErase);
delete(toErase->second);
}
}
template <typename M> void clear2( M *myMap )
{
if(myMap == NULL) return;
for ( typename M::iterator it = myMap->begin(); it != myMap->end(); ++it ) {
delete it->second;
}
myMap->clear();
}
class MY_CLASS
{
public:
int counter;
string *message;
MY_CLASS(int c, string *m):counter(c), message(m) {
std::cout << "Constructor MY_CLASS " << this << std::endl;
};
~MY_CLASS()
{
if(message) {
cout << "Being destroyed MY_CLASS: " << *message << " this = " << this <<endl;
}
else {
cout << "Being destoyed MY_CLASS: " << " this = " << this <<endl;
}
if(message) {
delete message;
message = NULL;
}
}
MY_CLASS(const MY_CLASS & other)
{
std::cout << "Copy Constructor MY_CLASS " << this << std::endl;
//1.
counter = other.counter;
//2.
if(other.message) {
message = new string;
*message = *other.message; // copy the value
}
else {
message = NULL;
}
}
};
void print(const string *str,MY_CLASS *& value, void *)
{
if (value && value->message)
cout << value->counter << " ! " << *(value->message) << endl;
}
int main() {
std::map<std::string, MY_CLASS *> *mpa = new std::map<std::string, MY_CLASS *>;
MY_CLASS *p = new MY_CLASS(2, new string("abc"));
mpa->insert(std::pair<std::string, MY_CLASS *>("1", p));
mpa->insert(std::pair<std::string, MY_CLASS *>("2", p));
clearAndDestroy(mpa);
delete mpa;
return 0;
}
Output:
Constructor MY_CLASS 0x111ccb0
Being destroyed MY_CLASS: abc this = 0x111ccb0
Being restricted to C++98 is clearAndDestroy my best option? Thank you!

Another approach you can take is using an object wrapper. Place the pointer you want within an object and have the destructor call the delete on the pointer. Basically building a simple "smart-pointer".
class AutoDeletePtr {
MY_CLASS* pointer;
AutoDeletePtr(MY_CLASS* myObjectPtr) {pointer = myObjectPtr};
~AutoDeletePtr() {delete(pointer)};
}
You can insert these objects into the std::map.

Related

How to make variable in companion object protected

I want to make a variable in companion object protected. I think when I make the variable protected, it would be accessible only from another class which inherit the variable's class, not from other classes or functions. But It doesn't work.
Here's my code
open class Population{
companion object{
#JvmStatic // Though I added it because of recommendation of IntelliJ, It still doesn't work.
protected var population_quantity: Int = 0
}
}
class Marin : Population(){
init{
population_quantity += 1 // I want to make it possible
}
}
class Checker : Population() {
fun printPopulationQuantity()
{
println(population_quantity) // I also want to make it possible
}
}
fun main(){
var m1 = Marin()
var checker = Checker()
// But I want to make codes below here impossible
// Population.population_quantity += 1
// println(Population.population_quantity)
}
Below is what I want to make which is made via C++. I hope below would clarify what I'm saying.
#include <iostream>
class Population
{
protected:
static int population_quantity;
};
int Population::population_quantity = 0;
class Marin : Population
{
public:
Marin()
{
std::cout << "Marin is generated" << std::endl;
population_quantity += 1;
}
~Marin()
{
std::cout << "Marin is dead" << std::endl;
population_quantity -= 1;
}
};
class Checker : Population
{
public:
void printPopulationQuantity()
{
std::cout << population_quantity << std::endl;
}
};
int main()
{
Checker checker;
checker.printPopulationQuantity();
Marin *m1 = new Marin();
checker.printPopulationQuantity();
// std::cout << "population : " << Population::population_quantity << std::endl;
// Can't access population_quantity from main which doesn't inherite Population
// because Population::population_qantity is protected.
// But it is possible to access Population:population_quantity from Marin which inherits Population.
delete m1;
checker.printPopulationQuantity();
return 0;
}
When you help me solve this problem, I'm sure that I would feel sincere thankful from bottom of my heart.
That is probably because in class Checker : Population you have a void function which is in public.
Try changing it to this:
class Checker : Population
{
protected:
void printPopulationQuantity()
{
std::cout << population_quantity << std::endl;
}
};

Defining strict_real_policies for reals with a comma decimal character

I would like to create a custom policy derived from strict_real_policies that will parse reals, such as "3,14", i.e. with a comma decimal point as used e.g. in Germany.
That should be easy, right?
#include <iostream>
#include <string>
#include <boost/spirit/home/x3.hpp>
template <typename T>
struct decimal_comma_strict_real_policies:boost::spirit::x3::strict_real_policies<T>
{
template <typename Iterator>
static bool
parse_dot(Iterator& first, Iterator const& last)
{
if (first == last || *first != ',')
return false;
++first;
return true;
}
};
void parse(const std::string& input)
{
namespace x3=boost::spirit::x3;
std::cout << "Parsing '" << input << "'" << std::endl;
std::string::const_iterator iter=std::begin(input),end=std::end(input);
const auto parser = x3::real_parser<double, decimal_comma_strict_real_policies<double>>{};
double parsed_num;
bool result=x3::parse(iter,end,parser,parsed_num);
if(result && iter==end)
{
std::cout << "Parsed: " << parsed_num << std::endl;
}
else
{
std::cout << "Something failed." << std::endl;
}
}
int main()
{
parse("3,14");
parse("3.14");
}

passing a class variable to API function

I want to track a global variable that I am passing into an API function. I found that one could do it using a class:
template <class T>
class MonitoredVariable
{
public:
MonitoredVariable() {}
MonitoredVariable(const T& value) : m_value(value) {}
//T operator T() const { return m_value; }
const MonitoredVariable& operator = (const T& value)
{
PlugIn::gResultOut << "value changed " << std::endl;
m_value = value;
return *this;
}
private:
T m_value;
};
The API function takes variables as
bool APIFunction(double time, bool *is_done, double *fraction_done);
The following gives me an error:
ImagePtr Im;
bool is_done;
MonitoredVariable<double*> fraction_done;
bool frameready = Im->APIFunction(2.1, is_done, fraction_done);
ERROR:
error C2664: cannot convert argument 3 from 'MonitoredVariable<double *>' to 'double *'
what would I have to change here?
thx!
I'm not really sure if this is what you want:
#include <iostream>
using namespace std;
template <class T>
class MonitoredVariable
{
public:
MonitoredVariable() {}
MonitoredVariable(const T& value) : m_value(value) {}
//T operator T() const { return m_value; }
const MonitoredVariable& operator = (const T& value)
{
//PlugIn::gResultOut << "value changed " << std::endl;
m_value = value.m_value;
return *this;
}
void printValue() {
std::cout << m_value;
}
T& getValue() {
return m_value;
}
private:
T m_value;
};
bool func(double firstDouble, bool *is_done, double* fraction_done) {
// do stuff
*fraction_done = firstDouble + (40.23 * 5);
*is_done = true;
return true;
}
int main()
{
bool is_done = true;
MonitoredVariable<double> fraction_done;
func(2.10, &is_done, &fraction_done.getValue());
fraction_done.printValue();
return 0;
}
So basically we have a Class called MonitoredVariable which has a variable called m_value. I'm not really sure why you wanted it to be a pointer, because we can also take the address of a normal double variable.
In the following it makes perhaps more sense what I want to achieve. I want to input a class variable into an API function and monitor the variable in real time. This value goes from zero to 1 every 3 ms or so. Yet I try to avoid using while loop and track it within the class with overloaded = operator.
#include "stdafx.h"
#include <iostream>
#include <thread>
#include <future>
using namespace std;
template <class T>
class MonitoredVariable
{
public:
MonitoredVariable() {}
MonitoredVariable(const T& value) : m_value(value) {}
void printValue() {
std::cout << m_value;
}
const MonitoredVariable& operator = (const T& value)
{
m_value = value.m_value;
if(m_value> 0.8) std::cout << m_value; // *THIS NEVER GETS PRINTED!!!*
return *this;
}
T& getValue() {
return m_value;
}
private:
T m_value;
};
bool func(bool *is_done, double* fraction_done) {
unsigned long c = 1;
while (*is_done)
{
*fraction_done = (double) 0.01*c;
this_thread::sleep_for(chrono::milliseconds(10));
c++;
if (*fraction_done >= 1) *is_done = false;
}
return true;
}
int main()
{
bool is_done = true;
MonitoredVariable<double> *MonitoredVariablePtr = new MonitoredVariable<double>();
std::future<bool> fu = std::async(std::launch::async,func, &is_done, &MonitoredVariablePtr->getValue());
// IF I UNCOMMENT THIS, IT PRINTS...
/*
while(is_done)
{
if(MonitoredVariablePtr->getValue() > 0.8) MonitoredVariablePtr->printValue();
}
*/
return 0;
}
Why does not the (if(m_value> 0.8) std::cout << m_value) line within the class never gets printed when the value is updated?
THX!

Segmentation Fault 11 in while loop dependent on std::map.count()

Within the definition of a class template method, the following lambda definition has been included:
//lambda
auto fnd_nxt_free = [&] ()
{
while(m_map.count(it->first))
{
DBG_PRINT("it->first:" << it->first)
DBG_PRINT("m_map.count(it->first):" << m_map.count(it->first))
DBG_PRINT("distance(m_map.begin(), it):" << distance(m_map.begin(),it))
if(it->first == keyEnd)
{
break;
}
++it;
}
return it;
};
The lambda is used to increment the iterator to the map, for the purpose of assignment.
For consecutive assignments to the map following construction, the intended logic of the code is to increment the iterator to the next free key position within the specified range, before insertion of the specific value.
The different values used in this particular test are (0,1,'A'), which corresponds to construction, (0,2,'B') and (0,3,'C'). Note that the range is implied as [keyBegin, keyEnd).
The segmentation fault is encountered for the third insertion inside the lambda fnd_nxt_free. Notice the debug prints highlighted inside the lambda as part of the source code. The corresponding output (for the third insertion) is as shown below:
it->first:0
m_map.count(it->first):1
distance(m_map.begin(), it):0
it->first:1
m_map.count(it->first):1
distance(m_map.begin(), it):1
it->first:1
m_map.count(it->first):1
distance(m_map.begin(), it):2
The output of m_map.count(<key>) is expected to be 0 when the distance of the iterator from m_map.begin() is 2, for the insertion (0,3,'C'). As the debug print output shows, the value of key is printed correctly in the first two cases, but does not increment after that, even though the distance of the iterator from m_map.begin() is shown to be 2.
In the case of the second insertion (0,2,'B') the same logic in the lambda works as expected, and the while() loop exits when the iterator is incremented past the first key position (0), and the only debug print that is output from the lambda is:
it->first:0
m_map.count(it->first):1
distance(m_map.begin(), it):0
Thus in the second case, the as the iterator moves past the first key position, mm_count() returns 0. However, the same logic fails in the case of the second insertion. I can assure that the rest of the processing before the lambda is hit is exactly the same in both the cases.
Can someone point to the flaw?
MWE
#define DBG_PRINT(...) (cout << __VA_ARGS__<< endl);
template<class K, class V>
class interval_map{
friend void IntervalMapTest();
private:
map<K,V> m_map;
private:
bool did_assign;
public:
interval_map(V const&);
public:
void assign(K const& keyBegin, K const& keyEnd, V const& val);
public:
V const& operator [](K const& key) const;
public:
struct comp;
public:
void display(void);
};
template<class K, class V> struct interval_map<K,V>::comp{
bool operator()(pair<K const&,V const&> p, V const& v) const{
return(p.second < v);
}
bool operator()(V const& v, pair<K const&, V const&> p) const{
return(v < p.second);
}
};
template<class K, class V> interval_map<K,V>::interval_map(V const& val){
m_map.insert(m_map.begin(), make_pair(numeric_limits<K>::lowest(), val));
}
template<class K, class V> V const& interval_map<K,V>::operator [] (K const& key) const{
return (--m_map.upper_bound(key))->second;
}
template<class K, class V> void interval_map<K,V>::assign(K const& keyBegin, K const& keyEnd, V const& val){
auto begin = m_map.find(keyBegin);
auto end = m_map.find(keyEnd);
auto p = equal_range(begin,end,val,comp());
auto it = p.first;
//lambda
auto fnd_nxt_free = [&] (){
LINE
while(
m_map.count(it->first)
){
DBG_PRINT("it->first:" << it->first)
DBG_PRINT("m_map.count(it->first):" << m_map.count(it->first))
DBG_PRINT("distance(m_map.begin(), it):" << distance(m_map.begin(), it))
if(it->first == keyEnd){
break;
}
++it;
}
return it;
};
if(it == end)
{
it = m_map.begin();
next(it,keyBegin);
fnd_nxt_free();
if(it->first < keyEnd){
m_map.insert(make_pair(it->first,val));
}
}
else{
if(p.second == end){
auto tmpKey = it->first;
do
{
if(fnd_nxt_free()->first < keyEnd)
{
if( fnd_nxt_free()->first - tmpKey < 2)
{
if(it == end){
break;
}
++it;
continue;
}
else
{
if(it->first < keyEnd){
m_map.insert(make_pair(it->first, val));
}
}
}
}while(it->first < keyEnd);
}
else{
it = p.second;
fnd_nxt_free();
if(it->first < keyEnd){
m_map.insert(make_pair(it->first,val));
}
}
}
}
template<class K, class V> void interval_map<K,V>::display(){
for(auto i : m_map){
cout << i.first;
cout << " ";
cout << i.second;
cout << endl;
}
}
void IntervalMapTest(){
interval_map<unsigned int, char> iMap('A');
iMap.assign(0,2,'B');
iMap.assign(0,3,'C');
iMap.display();
return;
}

GTKmm application: Gdk key press signals not firing

I have (sort of) copied (but with some modifications) the example in the GTKmm tutorials on keyboard events. (link)
https://developer.gnome.org/gtkmm-tutorial/stable/sec-keyboardevents-overview.html.en#keyboardevents-simple-example
Here is my code:
#include <gtkmm/application.h>
#include <gtkmm/window.h>
#include <gtkmm/textview.h>
#include <iostream>
class MainWindow
{
public:
MainWindow()
{
_window_.set_default_size(600, 400);
_window_.add(_textview_);
Glib::RefPtr<Gtk::TextBuffer> textbuffer_rp{_textview_.get_buffer()};
textbuffer_rp->set_text("some text here");
_textview_.set_monospace();
_window_.add_events(Gdk::KEY_PRESS_MASK);
_window_.show_all_children();
}
Gtk::Window &get_window()
{
return _window_;
}
protected:
bool on_key_press_event(GdkEventKey* event)
{
std::cout << "some keypress event" << std::endl;
if
(
(event->keyval == GDK_KEY_H) &&
((event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK) == GDK_CONTROL_MASK))
)
{
std::cout << "Hello world!" << std::endl;
}
if
(
(event->keyval == GDK_KEY_C) &&
((event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK) == GDK_CONTROL_MASK))
)
{
signal_textview_CTRL_C();
}
else if
(
(event->keyval == GDK_KEY_V) &&
((event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK) == GDK_CONTROL_MASK))
)
{
signal_textview_CTRL_V();
}
else
{
std::cout << "unhandled key" << std::endl;
}
return true;
}
void signal_textview_CTRL_C()
{
_text_register_0_ = "some text gets put here";
}
void signal_textview_CTRL_V()
{
Glib::RefPtr<Gtk::TextBuffer> textbuffer_rp{_textview_.get_buffer()};
textbuffer_rp->set_text(_text_register_0_);
}
private:
Gtk::Window _window_;
Gtk::TextView _textview_;
Glib::ustring _text_register_0_;
};
int main(int argc, char *argv[])
{
auto app = Gtk::Application::create(argc, argv, "org.gtkmm.examples.base");
MainWindow mainwindow;
return app->run(mainwindow.get_window());
}
However it is not working - none of the signal events appear to fire when I press the key sequences CTRL-C, CTRL-V, CTRL-H.
I think I have stripped all the irrelevant stuff from the code so this should be a working MWE.
Connect your handler as first.
_window_.signal_key_press_event().connect(sigc::mem_fun(*this, &MainWindow::on_key_press_event), false);
Return false to let _textview_ get the key.
Your conditions are contradictory.
GDK_KEY_H is keysym for shift+h. Then you check (event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK) == GDK_CONTROL_MASK). You are asking if state (which we know is with GDK_SHIFT_MASK) is ONLY GDK_CONTROL_MASK.
Code:
#include <gtkmm/application.h>
#include <gtkmm/window.h>
#include <gtkmm/textview.h>
#include <iostream>
class MainWindow
{
public:
MainWindow()
{
_window_.set_default_size(600, 400);
_window_.add(_textview_);
Glib::RefPtr<Gtk::TextBuffer> textbuffer_rp{_textview_.get_buffer()};
textbuffer_rp->set_text("some text here");
_textview_.set_monospace();
_window_.add_events(Gdk::KEY_PRESS_MASK);
_window_.signal_key_press_event().connect(sigc::mem_fun(*this, &MainWindow::on_key_press_event), false);
_window_.show_all_children();
}
Gtk::Window &get_window()
{
return _window_;
}
protected:
bool on_key_press_event(GdkEventKey* event)
{
std::cout << "some keypress event " << std::hex<<event->keyval<<" "<<std::hex<<event->state<<std::endl;
if
(
(event->keyval == GDK_KEY_h) &&
(event->state & GDK_CONTROL_MASK)
)
{
std::cout << "Hello world!" << std::endl;
return true;
}
if
(
(event->keyval == GDK_KEY_c) &&
(event->state & GDK_CONTROL_MASK)
)
{
std::cout<<"ctrl c"<<std::endl;
signal_textview_CTRL_C();
return true;
}
else if
(
(event->keyval == GDK_KEY_v) &&
(event->state & GDK_CONTROL_MASK)
)
{
std::cout<<"ctrl v"<<std::endl;
signal_textview_CTRL_V();
return true;
}
else
{
std::cout << "unhandled key" << std::endl;
}
return false;
}
void signal_textview_CTRL_C()
{
_text_register_0_ = "some text gets put here";
}
void signal_textview_CTRL_V()
{
Glib::RefPtr<Gtk::TextBuffer> textbuffer_rp{_textview_.get_buffer()};
textbuffer_rp->set_text(_text_register_0_);
}
private:
Gtk::Window _window_;
Gtk::TextView _textview_;
Glib::ustring _text_register_0_;
};
int main(int argc, char *argv[])
{
auto app = Gtk::Application::create(argc, argv, "org.gtkmm.examples.base");
MainWindow mainwindow;
return app->run(mainwindow.get_window());
}