Totally impossible

closed account (SECMoG1T)
Last week i decided to write an application, quite large to use most of c++ facilities that av learnt so far just for fun, however i faced a bunch of problems that really choked my creativity in the first phase of my app but than i got some help , solved the main problems and ignored the rest coz i could still do without them but then there is this quite interesting one that got my mind totally twisted up n if possible i would like to know how i would have solved it ,might be i'll need the solution somewhere else i never know.

Description:
The problem was about tracking the number of copies generated per each class
instance, it seemed quite easy but i was wrong.

for example , i might have a class Foo then create two objects named Foo_obj1
and Foo_obj2, for my case i had a function called generate_n_copies that took an object,a count and returned a vector of count objects created using copy assignment operator only, also each copy created was assigned a numeric number to denote it's copy number.

so if i called
1
2
3
4
5
6
7
8
9
10
 
    auto vec=generate_n_copies(Foo_obj1,10);
    ///the last item should have copy number as 11.
    /// if i also called the function again like this

    auto vec2=generate_n_copies(vec[7],10);///problematic exception
    ///i intended to have last item  assigned 21 as it's copy number
    ///because they are all copies of Foo_obj1
   /// Note : Foo_obj1 copy number==1;
  


I had 3 possible options to track my copies.

1. using a static variable - failed because i din't realize the variable would
belong to the class- the logic error was that all
instances of the class would use the same variable.
i.e Foo_obj1 and Foo_obj2 used the same variable.

2. using a stack/heap variables - could track the copies but failed on the
part labeled exception.

3. hybrid -> heap & static variable - failed as the first one.

The code for all the three instances is still available.

Conclusion: Totally impossible

If anyone got a nice idea on how to take this beast down i would really
appreciate.
Last edited on
Could you show the code from generate_n_copies()?
closed account (SECMoG1T)
Here is the code

1
2
3
4
5
6
7
8
9
10
11
template<typename T>
std::vector<T> generate_n_copies(const T& T_obj,std::size_t Count)
{
    std::vector<T> local_vec(Count);

    std::size_t i=0;
    while(i<Count)
        local_vec[i++]=T_obj;

    return local_vec;
}


Thanks.
Last edited on
closed account (SECMoG1T)
Here is my first test using a static variable

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include <iostream>
#include <string>
#include <vector>
#include <ctime>
#include <random>

///the reason i used this stuct is because i thought giving my data class a member with a
///a static variable would allow each instance to own a static variable, i was wrong
struct Cpy_control
{
    static std::size_t Count;
};

std::size_t Cpy_control::Count=1;

struct DataClass
{
    std::string mem;
    mutable Cpy_control Cpy_ref;
    DataClass():Cpy_ref(),mem(std::to_string(Cpy_ref.Count)){}
    DataClass& operator= (const DataClass& em);
    DataClass(const DataClass&);
};

template<typename T>
std::vector<T> generate_n_copies(const T& T_obj, std::size_t Count)
{
  std::vector<T> local_vec(Count);

  std::size_t i=0;
  while(i<Count)
    local_vec[i++]=T_obj;

  return local_vec;
}


DataClass& DataClass::operator =(const DataClass& em)
{
   ++(em.Cpy_ref.Count);
   mem=std::to_string(em.Cpy_ref.Count);
    return *this;
}

DataClass::DataClass(const DataClass& em)
{
   mem=std::to_string(em.Cpy_ref.Count)+"_copy";;
}

void print(const std::vector<DataClass>& vec)
{
    std::cout<<"\n\n";
    for(const auto& item : vec)
       std::cout<<item.mem<<std::endl;
    std::cout<<"\n\n";
}

int main()
{
    /*******************************************/
    DataClass data_obj;
    auto Data_vec1=generate_n_copies(data_obj,20);

    print(Data_vec1);
    ///pass
    /*******************************************/
    auto Data_obj_cpy1=Data_vec1[10];
    auto Data_vec2=generate_n_copies(Data_obj_cpy1,20);

    print(Data_vec2);
    ///pass
    /*******************************************/
    std::mt19937 mt_rng(std::time(nullptr));
    std::uniform_int_distribution<std::size_t> u_dist(0,20);

    auto Data_obj_cpy2=Data_vec2[(u_dist(mt_rng))];
    auto Data_vec3=generate_n_copies(Data_obj_cpy2,34);

     print(Data_vec3);

     ///pass

   /*******************************************/
   ///failed here
   DataClass new_obj;
        std::cout<<"\t\t\treport mem value : "<<new_obj.Cpy_ref.Count<<std::endl<<std::endl;
   auto Data_new_vec=generate_n_copies(new_obj,37);

    print(Data_new_vec);
}


Using a heap variable also failed
http://pastebin.com/YSTHLDqu

Static & heap// failed
http://pastebin.com/PTTwiv8v
Last edited on
Cpy_ref makes no sense. It's an empty struct like a namespace:
1
2
3
4
namespace Cpy_control
{
    static std::size_t Count;
}
is equivalent.

1
2
3
4
5
6
7
8
9
10
11
struct DataClass
{
    std::string mem;
    //mutable Cpy_control Cpy_ref;

std::size_t Index; // This is the index of each object

    DataClass():Index(Cpy_control::Count),mem(std::to_string(Cpy_control::Count)){++(Cpy_control::Count);} // Increase the count here not in operator=()
    DataClass& operator= (const DataClass& em);
    DataClass(const DataClass&);
};

There is already entity in standard library which keeps track of own copies: shared pointer. You can look into how is it implemented and do something similar.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <memory>

class foo
{
    std::shared_ptr<int> counter {std::make_shared<int>()};
  public:
    std::size_t copies() {return counter.use_count();}
};

int main()
{
    foo x;
    foo y;
    foo z(x);
    std::cout << x.copies() << ' ' << y.copies() << '\n';
    z = y;
    std::cout << x.copies() << ' ' << y.copies() << '\n';
}
2 1
1 2
closed account (SECMoG1T)
Thanks @coder, i just told yah i got totally twisted, that's just a sign of some desperate moves that i attempted, hehe :D

DataClass():Index(Cpy_control::Count),mem(std::to_string(Cpy_control::Count)){++(Cpy_control::Count);}

Thanks but this isn't the behavior i want, basically the class constructor should initialize a new object to a count of 1, what i wanted to track was the number of copies generated per each object and that could only be done using the copy assignment operator, lemmi give another example

For example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Foo
{
   public:
    ///functions
  private:
    std::size_t copy_no;//holds the copy number
    std::string name;///just for emphasis
   ///others
}

///if i create some objects each object should have it's copy_no equal to 1 as
/// it is the first instance of that kind

Foo Shoe("Nike vapour"), Gloves("Addidas vectra"), Ball("Mitre cyclone");

///here av got a single instance of each object, lets say i would like to have 
///20 copies Mitre cyclone soccer ball from my object "Ball" , i would use the copy
/// assignement operator to produce the 20 new copies, each of those new objects
/// copy_number member would be assigned a value by the assignment operator
///with the last object having 21 as its copy number.

///if i picked the 7th copy object and create another 10 copies , here the first object 
///should have the copy number as 22 and the last object 32 since they are all instances
/// of the same object "Ball".


That's is all i wanted to achieve.



Last edited on
closed account (SECMoG1T)
@MiiNipaa Am trying to understand that code
That's is all i wanted to achieve.
Well then it's a reference count similar to what MiiNiPaa pointed out.

I just wonder why you want to create the exact object again. In my eyes a waste of memory. Why not so:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Foo
{
   public:
    ///functions
  private:
    std::string name;
    std::size_t available_count;
   ///others

public:
Foo(const std::string &a, std::size_t amount) : name(a), available_count(amount)
};


Foo Shoe("Nike vapour", 5), Gloves("Addidas vectra", 10), Ball("Mitre cyclone", 20);
Last edited on
closed account (SECMoG1T)
I just wonder why you want to create the exact object again. In my eyes a waste of memory. Why not so: @Coder777 no it's all i could think of

lemmi give you a preview of my application

The app have got four sections

1. a library{books, movies,hits}
2. store {as above + electonics, sportwares}+ some more
3. user management-> users can create acounts,delete accounts, buy items, loan items
from the library e.t.c
4. Admin - admin can track the amount objects in the stores and library, request for new
supplies etc.

All that is no real system, it's just a simulation that am still working on till today, now i might have more that ten copies of each object in the library i.e books,movies... the copy number was just to help the admin to know when to request for new copies from the suppliers and also track the objects that have been borrowed from the library or bought from the store etc.

I hope that will explains why i needed the count variable.

Last edited on
> track the objects that have been borrowed from the library
¿do you really need to track the objects?
¿is it not enough to just have two counters, `total' and `not_here_right_now_but_we_do_have_them'?

If you do want to track them you may just give an identifier to every book. There is no need for it to be related with the quantity of copies that you've got (which can be calculated by other means)


Also, it's quite wasteful for each copy to repeat the book information
1
2
3
4
class BookItem{
   int id;
   std::shared_ptr<BookType> the_book; //ISBN, title, references the author, ...
};
Last edited on
closed account (SECMoG1T)
Hey @ne555 thank you but there is still more to do with my objects, for example am almost through implementing my data classes to represent the objects such as book's, movies etc.

Reason for tracking my copies:

For example I have 5 book classes which are related by inheritance
1. An abstract base class
2 . a short_loan_books class - users can borrow books upto max=7 days, any extra day should be
charged
3. normal_loan_books - " " " " max=14 days, " " " "
4. Misclleneous_books _ represent journals, magazines such this can be borrowed only for
One day
5. Books_for_sale - found in store , can only be bought.


If the user borrows a particular copy of a book n than the user labels that books as lost in his/her account the admin should know that a particular copy with a unique ID "*******" got lost n that user should pay for that book and any extra day since the max loaning period.


Last edited on
short/long/etc. books are better represented by aggregation, not inheritance.

So you will have:
class Book; — abstract book itself, author, title, ISBN...
class Lease_terms; — terms of lease (amount of days/charge...)
1
2
3
4
5
6
class book_instance
{
    const Book book; //What this book is
    Lease_terms lease; //What the terms are
    std::string comment; //Other data...
}
— concrete book. That way you can easily change terms of lease for certain book, can have different terms for different instances of same book (for example 3 books for short termlease and 7 for sale), etc.
For example I have 5 book classes which are related by inheritance
This is not a good idea. Inherit only if you want to extent functionality.

e.g:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
struct item
{
  std::string type;
  std::string name;
  int amount;
};
struct stock_item : item
{
  int loan_days; // 0 means cannot be loaned
  bool can_buy;
};
struct user_item : item
{
  date loan_date;
};
struct user
{
  std::vector<item> cart_vector;
  std::vector<user_item> loan_vector;
};


admin should know that a particular copy with a unique ID "*******" got lost n that user should pay for that book and any extra day since the max loaning period.
An id isn't necessary in that case. That the user has still loan items in his struct allows the admin to calculate the extra fee.
If you have a physical book you have the ISBN or article number. These numbers are generated when an item is put into stock. Then an item may look like this:
1
2
3
4
5
6
struct item
{
  std::string type;
  std::string name;
  std::vector<std::string> id_vector;
};
Last edited on
closed account (SECMoG1T)
Thanks @MiiNipaa and @Coder7 - i think yesterday i realized how terrible my design was so i decided to head back to the drawing board and come up with some new logic based on the advice av got this far : i'll be implementing everything from scratch n by now i have
two new classes to control the state of my objects, should i change anything:-

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#ifndef _UTILITY_H
#define _UTILITY_H

#include <cstdlib>

namespace APP_SPACE
{

	class lease_terms
	{
	 public:
		explicit lease_terms(std::size_t max_days = 0, double chrg = 0.0)
			:max_loan_period(max_days), charge_per_xtrday(chrg){}

		double get_charge() const;
		std::size_t get_max_days() const;
	 private:
		const std::size_t max_loan_period;
		const double charge_per_xtrday;
	};

	class item_state
	{
	public:
		explicit item_state(bool can_lease = false, bool itm_brrwd = false, bool itm_lst = false)
			:can_borrow_itm(can_lease), item_borrowed(itm_brrwd), item_lost(itm_lst) {}

		///setters
		void set_can_lease(){ can_borrow_itm= true; }
		void set_borrowed (){ item_borrowed = true; }
		void set_lost  (){ item_lost = true; }
		void set_returned(){ item_borrowed = false; }
		void set_restored(){ item_lost = false;  }


		///getters
		bool can_borrow_item() const{ return can_borrow_item; }
		bool item_in_stock() const{ return !(item_borrowed); }
		bool item_got_lost() const{ return item_lost; }
	  private:
		bool  can_borrow_itm;
		bool  item_borrowed;
		bool  item_lost;
	};

}
#endif  //_UTILITY_H 
Last edited on
I suggest to read book Refactoring: Improving the Design of Existing Code by Martin Fowler. In the first chapter there is an example of improving classes for hadling movie rental explaining reasons behind every change.

For example, in your class set_late() is useless. It requires manual handling of information which should be handled by class itself. is_late() should calculate amount of days passed (from current date and borrow date) and querry lease terms if book is late if it is borowed for n days.
closed account (SECMoG1T)
@MiiniPaa thank you, surely that makes sense , am correcting that now , am really gaining a lot from this thanks again-- am learning of new tricks that maybe i wouldn't have come across easily, for the book you recommended i'll make sure i get it on time, am sure it's worth .

This app is a milestone that i have to set, well it's way better then the last text based game that i made n requires so me extra efforts, I hope you guys will help me through this.

I appreciate this :D
Topic archived. No new replies allowed.