genericity

Hello, I'm french so please forgive me if the vocabulary doesn't fit the English standard.

I'm trying to make a generic class called Type with the help of templates.
So I think I would define it like that
1
2
3
4
5
6
7
8
9
10
11
12
template <typename T> Type{
 public:
  Type();
  ~Type();
  generic methods();
 private:
  T value;
  static int count;
 ...

} 


Several questions from there.
The first and most important is , how do I factor from here?
Can I do a class
1
2
3
4
5
6
7
8
class MyInt: public Type<int>{
 public:
  MyInt();//should I add a new constructor? Should Type and ~Type be void?
  specific methods();
 private:
  new attributes and private methods ...
} 

If not, how can I do both genericity and add some specific function inside a sub class?
If yes, if I increase MyInt::count would it increase for all instances of Type?
Thanks.
> can I do both genericity and add some specific function inside a sub class?

Yes.


> if I increase MyInt::count would it increase for all instances of Type?

No. Each instantiation of the template would have its own copy of the static data member.

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
#include <iostream>

template < typename T > struct type
{
    /*explicit*/ type( T val = {} ) : value( std::move(val) ) { ++instance_count ; } // constructor
    ~type() { --instance_count ; }
    // etc.

    operator T& () noexcept { return value ; }
    operator const T& () const noexcept { return value ; }

    static unsigned long long count() noexcept { return instance_count ; }

    private:
        T value ;
        static unsigned long long instance_count ;
};

template < typename T > unsigned long long type<T>::instance_count = 0 ;

struct Integer : type<int>
{
     using base = type<int> ;
     using base::base ; // inherited constructor
};

int main()
{
    Integer i = 22 ;
    std::cout << "i == " << i << '\n' ; // 22
    i += 30 ; // i.operator int&() += 30 ;
    std::cout << "i == " << i << '\n' ; // 52

    std::cout << "count == " << Integer::count() << '\n' ; // 1

    {
        const Integer arr[5] { 1, 2, 3, 4, 5 } ; // 5 sub-objects
        std::cout << "count == " << Integer::count() << '\n' ; // 6
        
        const type<double> dbl[22] {} ; // 22 sub-objects
        std::cout << "count == " << Integer::count() << '\n' ; // 6
        std::cout << "count (double) == " << type<double>::count() << '\n' ; // 22
        
        // array arr is destroyed
    }

    std::cout << "count == " << Integer::count() << '\n' ; // 1
}

http://coliru.stacked-crooked.com/a/1054988acd5b9f5c
Last edited on
count is only static for each T
so type<double> d and type<int> i has 2 static variable count instances. If you then say type<int> i2, then i and i2 share the static int count variable, and d (double) one is unaffected by changes to the int one.

I see no reason for empty constructors or destructors in either class here. But that depends on what all the other stuff in your classes really is, as these are empty examples.

If instance counts are to be tracked, explicitly defined constructors and destructor would be needed in the base class.
Ok thanks both of you. It answers my questions.
We were told to always put a constructor and a destructor, but actually I was wondering if I was not creating too many objects if I put two of them, one in the parent class and the other in the child.
a constructor does not create more objects.
if it is not in the code, C++ supplies a basic one that is identical to an empty one.
Topic archived. No new replies allowed.