Template class imitating an ordinary variable

Hi there,

I have to write a template class which will be imitating an ordinary variable such as int. It has to be based on dynamic allocation. Following is an example:

1
2
3
4
5
6
7
8
9
10
11
12
13
 { Wrapper < double> el1, el2;

el1=3.8;//el1=new double, *el1 = 3.8, counter=1
el2=el1;//counter=2

if(1){
Wrapper< double> el3;

el3=el2;//counter=3
                              
} //counter=2, free el3

} // counter=0, free el1, el2 


It should include handy and useful overloaded operators and functions. Besides, I have to implement proper exception handling (according to my prerequisites, the following throws are incorrect: throw 7 or throw "Error in module foo).

So here are my questions:

1) What is proper exception handling? I should derive my own exception class from the standard one named exception?

2) Where are potentially dangerous places in such class to throw an exception?

3) What useful overloaded operators along with operator+ or operator- should I embed into my class?

Regards.
Last edited on
> What is proper exception handling? I should derive my own exception class from the standard one named

Not necessarily. You could throw std::overflow_error or std::invalid_argument.
And ideally catch them by reference to const.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
try
{
    // ...
}  

catch( const std::overflow_error& o ) 
{
    // handle overflow
}

catch( const std::exception& e )
{
    // handle other errors
}


> Where are potentially dangerous places in such class to throw an exception?

In the normal case, in destructors, move constructors or move assignment operators.

However, if you hold raw resources, everywhere.


> What useful overloaded operators along with operator+ or operator- should I embed into my class?

Other than conversion operators, only those operators where you want to intercept and check for errors (overflow etc) are required. For example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <memory>
#include <stdexcept>

template< typename T > struct wrapper
{
    wrapper( const T& v = T() ) : p( new T(v) ) {}
    explicit wrapper( T*&& pp ) : p(pp) { if(!p) throw std::invalid_argument( "nullptr!" ) ; }
    // ...

    operator T& () { if(!p) throw std::domain_error( "dereference of nullptr!" ) ; return *p ; }
    operator const T& () const { if(!p) throw std::domain_error( "dereference of nullptr!" ) ; return *p ; }
    // ...

    std::unique_ptr<T> p ;
};

int main()
{
    wrapper<double> d1(23.4), d2( new double(5.8) ) ;
    std::cout << d1 * d2 << '\n' ;
}
Last edited on
Topic archived. No new replies allowed.