473,383 Members | 1,896 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,383 software developers and data experts.

Please help me see whether this is exception-safe

I have a set of classes, cell, cell_body, and cell_internal.

cell_internal is an abstract base class, intended to encapsulate
deferred computation.

cell is just a wrapped pointer around cell_body; this is the user's
interface to this code.
When a cell is created, it creates a cell_body and attaches a
shared_ptr member (value_) to the body. This shared_ptr should never
be changed; the cell can only have one cell_body during its lifetime.

The cell_body holds a pointer to a cell_internal; when the cell's
value is taken by the member get_value(), it calls cell_body's
get_value(), which calls cell_internal's virtual cell_value(). This
virtual cell_value then computes the correct value. Basically the
get_value() function performs the computation that has been deferred.

Copying a cell to a cell does not, in fact, copy the cell; instead,
the destination cell is "attached" to the source cell, so that
changing the value of one changes the value of the other. So:
cell<inti, j;
i = j;
j = 1; //now i is also 1
Actually what is being attached are the cell_body's. A new
cell_internal derived class (cell_shadow) is created, whose virtual
get_value() simply calls the get_value() of the cell_body it is
constructed with.

I don't use cell_body directly because of the possibility of
temporaries. When a cell is destroyed, its cell_body may still
survive, for example when referred from a global variable.

I think I may need to do swap-copy, but I don't quite understand yet
where I need to put it.

/*
* */

#include <boost/shared_ptr.hpp>
#include <boost/scoped_ptr.hpp>

/* cell_internal
* Interface to handle the deferred computation
* */
template<class T>
class cell_internal{
public:
virtual T get_value(void) const=0;
virtual ~cell_internal(){};
};

template<class T>
struct cell_internal_ptr{
typedef boost::shared_ptr< const cell_internal<T type;
};

/* cell_constant
* Handles constant numeric values
* */
template<class T>
class cell_constant: public cell_internal<T>{
T c_;
public:
cell_constant<T>(const T& v): c_(v) {};
T get_value(void) const {return c_;};
};

/* cell_body
* The actual cell structure
* */
template<class T>
class cell_body{
typename cell_internal_ptr<T>::type value_;
public:
cell_body(const cell_internal<T>* v): value_(v) {};
cell_body(const typename cell_internal_ptr<T>::type v): value_(v) {}
T get_value(void) const {
return value_->get_value();
};
void set(const cell_internal<T>* v){
value_.reset(v);
}
};

template<class T>
struct cell_body_ptr{
typedef boost::shared_ptr< const cell_body<T type;
};

/* cell_shadow
* Shadows a given cell_body
* */
template<class T>
class cell_shadow: public cell_internal<T>{
boost::shared_ptr< const cell_body<T var_;
public:
cell_shadow<T>(const cell_body<T>* v) : var_(v){};
cell_shadow<T>(const boost::shared_ptr< cell_body<T& v):
var_(v){};
T get_value(void) const {return var_->get_value();};
};

/* cell_op
* Handles a binary operation
* */
template<class T, class BinaryOperation>
class cell_op: public cell_internal<T>{
boost::shared_ptr< const cell_body<T lhs_;
boost::shared_ptr< const cell_body<T rhs_;
public:
cell_op<T, BinaryOperation>( const boost::shared_ptr< const
cell_body<T& lhs,
const boost::shared_ptr< const cell_body<T& rhs
) :
lhs_(lhs),
rhs_(rhs) { };
cell_op<T, BinaryOperation>( cell_body<T>* lhs, cell_body<T>* rhs):
lhs_(lhs),
rhs_(rhs) { };
T get_value(void) const {
return BinaryOperation()(lhs_->get_value(), rhs_->get_value());
};
};

/* cell_singelop
* Handles a unary operation
* */
//template<class T, class UnaryOperation>
//class cell_singleop: public cell_internal<T>{
//};

/* cell
* Acts as the user's interface to the cell_body
* Effectively just a wrapper around a pointer to the cell_body
* IMPORTANT. Each cell will have one, and only one, cell_body
* during its lifetime. A cell_body, however, may outlive its
* cell (for example if the cell is a local variable that is
* then used in the formula for a global variable - at the end
* of the function the local cell is destroyed, but the cell_body
* is retained via a cell_shadow by the formula for the global).
* */
template<class T>
class cell{
void set(const cell_internal<T>* v){
value_->set(v);
}
boost::shared_ptr< cell_body<T value_;
public:
cell<T>(const cell<T>& v){
value_.reset(new cell_body<T>(new cell_shadow<T>(v.value_)));
}
cell<T>(const T& v=T()){
value_.reset(new cell_body<T>(new cell_constant<T>(v)));
}
cell<T>(const typename cell_internal_ptr<T>::type& v){
value_.reset(new cell_body<T>(v));
}
cell<T>(const cell_internal<T>* v){
value_.reset(new cell_body<T>(v));
}

cell<T>& operator=(const cell<T>& v){
if(&v != this){
set(new cell_shadow<T>(v.value_));
}
}
cell<T>& operator=(const T& v){
set(new cell_constant<T>(v));
}
cell<T>& operator=(const typename cell_internal_ptr<T>::type& v){
set(&(*v));
}

cell<Toperator+(const cell<T>& rhs) const {
return cell<T>(
new cell_op<T, std::plus<T(
value_,
rhs.value_
)
);
};

T get_value(void) const {return value_->get_value();}
};

template<class T>
inline cell<Toperator+(const cell<T>& lhs, const T& rhs){
return lhs + cell<T>(rhs);
}

template<class T>
inline cell<Toperator+(const T& lhs, const cell<T>& rhs){
return cell<T>(lhs) + rhs;
}
Nov 17 '07 #1
1 1302
On 2007-11-17 00:47:57 -0500, alan <al******@gmail.comsaid:
I have a set of classes, cell, cell_body, and cell_internal.

cell_internal is an abstract base class, intended to encapsulate
deferred computation.

cell is just a wrapped pointer around cell_body; this is the user's
interface to this code.
When a cell is created, it creates a cell_body and attaches a
shared_ptr member (value_) to the body. This shared_ptr should never
be changed; the cell can only have one cell_body during its lifetime.

The cell_body holds a pointer to a cell_internal; when the cell's
value is taken by the member get_value(), it calls cell_body's
get_value(), which calls cell_internal's virtual cell_value(). This
virtual cell_value then computes the correct value. Basically the
get_value() function performs the computation that has been deferred.

Copying a cell to a cell does not, in fact, copy the cell; instead,
the destination cell is "attached" to the source cell, so that
changing the value of one changes the value of the other. So:
cell<inti, j;
i = j;
j = 1; //now i is also 1
If assignment to j can change i too, then this is telling me that
cell<intis acting like a pointer. So, please define it like a
pointer class.

One important principle I recently picked up is the principle of least
surprise. If it is intended to quake like a duck, then please call it
a duck. So, if cell<intacts like a pointer, then code it with syntax
like that of a pointer, so that readers of your code won't have to rely
on optional comments like "now i is also 1" to know that it behaves
like a pointer.

Try this:

cell_ptr<inti, j;
i = j;
*j = 1;

and declare the operator *() for the class cell_ptr.

This is much clearer.
Actually what is being attached are the cell_body's. A new
cell_internal derived class (cell_shadow) is created, whose virtual
get_value() simply calls the get_value() of the cell_body it is
constructed with.

I don't use cell_body directly because of the possibility of
temporaries. When a cell is destroyed, its cell_body may still
survive, for example when referred from a global variable.

I think I may need to do swap-copy, but I don't quite understand yet
where I need to put it.

/*
* */

#include <boost/shared_ptr.hpp>
#include <boost/scoped_ptr.hpp>

/* cell_internal
* Interface to handle the deferred computation
* */
template<class T>
class cell_internal{
public:
virtual T get_value(void) const=0;
virtual ~cell_internal(){};
};

template<class T>
struct cell_internal_ptr{
typedef boost::shared_ptr< const cell_internal<T type;
};

/* cell_constant
* Handles constant numeric values
* */
template<class T>
class cell_constant: public cell_internal<T>{
T c_;
public:
cell_constant<T>(const T& v): c_(v) {};
T get_value(void) const {return c_;};
};

/* cell_body
* The actual cell structure
* */
template<class T>
class cell_body{
typename cell_internal_ptr<T>::type value_;
public:
cell_body(const cell_internal<T>* v): value_(v) {};
cell_body(const typename cell_internal_ptr<T>::type v): value_(v) {}
T get_value(void) const {
return value_->get_value();
};
void set(const cell_internal<T>* v){
value_.reset(v);
}
};

template<class T>
struct cell_body_ptr{
typedef boost::shared_ptr< const cell_body<T type;
};

/* cell_shadow
* Shadows a given cell_body
* */
template<class T>
class cell_shadow: public cell_internal<T>{
boost::shared_ptr< const cell_body<T var_;
public:
cell_shadow<T>(const cell_body<T>* v) : var_(v){};
cell_shadow<T>(const boost::shared_ptr< cell_body<T& v):
var_(v){};
T get_value(void) const {return var_->get_value();};
};

/* cell_op
* Handles a binary operation
* */
template<class T, class BinaryOperation>
class cell_op: public cell_internal<T>{
boost::shared_ptr< const cell_body<T lhs_;
boost::shared_ptr< const cell_body<T rhs_;
public:
cell_op<T, BinaryOperation>( const boost::shared_ptr< const
cell_body<T& lhs,
const boost::shared_ptr< const cell_body<T& rhs
) :
lhs_(lhs),
rhs_(rhs) { };
cell_op<T, BinaryOperation>( cell_body<T>* lhs, cell_body<T>* rhs):
lhs_(lhs),
rhs_(rhs) { };
T get_value(void) const {
return BinaryOperation()(lhs_->get_value(), rhs_->get_value());
};
};

/* cell_singelop
* Handles a unary operation
* */
//template<class T, class UnaryOperation>
//class cell_singleop: public cell_internal<T>{
//};

/* cell
* Acts as the user's interface to the cell_body
* Effectively just a wrapper around a pointer to the cell_body
* IMPORTANT. Each cell will have one, and only one, cell_body
* during its lifetime. A cell_body, however, may outlive its
* cell (for example if the cell is a local variable that is
* then used in the formula for a global variable - at the end
* of the function the local cell is destroyed, but the cell_body
* is retained via a cell_shadow by the formula for the global).
* */
template<class T>
class cell{
void set(const cell_internal<T>* v){
value_->set(v);
}
boost::shared_ptr< cell_body<T value_;
public:
cell<T>(const cell<T>& v){
value_.reset(new cell_body<T>(new cell_shadow<T>(v.value_)));
}
cell<T>(const T& v=T()){
value_.reset(new cell_body<T>(new cell_constant<T>(v)));
}
cell<T>(const typename cell_internal_ptr<T>::type& v){
value_.reset(new cell_body<T>(v));
}
cell<T>(const cell_internal<T>* v){
value_.reset(new cell_body<T>(v));
}

cell<T>& operator=(const cell<T>& v){
if(&v != this){
set(new cell_shadow<T>(v.value_));
}
}
cell<T>& operator=(const T& v){
set(new cell_constant<T>(v));
}
cell<T>& operator=(const typename cell_internal_ptr<T>::type& v){
set(&(*v));
}

cell<Toperator+(const cell<T>& rhs) const {
return cell<T>(
new cell_op<T, std::plus<T(
value_,
rhs.value_
)
);
};

T get_value(void) const {return value_->get_value();}
};

template<class T>
inline cell<Toperator+(const cell<T>& lhs, const T& rhs){
return lhs + cell<T>(rhs);
}

template<class T>
inline cell<Toperator+(const T& lhs, const cell<T>& rhs){
return cell<T>(lhs) + rhs;
}
--

-kira

Nov 17 '07 #2

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

35
by: wired | last post by:
Hi, I've just taught myself C++, so I haven't learnt much about style or the like from any single source, and I'm quite styleless as a result. But at the same time, I really want nice code and I...
2
by: Joerg Battermann | last post by:
Hello there, I was wondering how I can check whether I am allowed to read a certain file or not? Some of e.g. XP's files are not readable, not even by the Administrator, and when trying to open...
3
by: John Ruiz | last post by:
Hello. I was wondering about exceptions and how to throw them within functions/methods and catch them. Suppose that we've got: ----------------------------------------------------------------...
11
by: Dale | last post by:
How to recognize whether file has XML format or not? Here is the code segment: XmlDocument* pDomDocument = new XmlDocument(); try { pDomDocument->Load(strFileName ) ; } catch(Exception* e) {
2
by: Chen Zhuo | last post by:
Hi, I need to write some code to test whether a folder has read/write permission. The idea is to try to read sub-directories in this folder, if succeed, then test whether it's read-only. Any...
1
by: Terrance | last post by:
Hello, I was wondering if someone can help me understand something. Below is some code that I got from the MS website that is suppose to authenticate for the username and password on the local...
1
by: Chukkalove | last post by:
I originally created several "copy" resource reader classes which worked great individually, but after I converted them into an parent class with children they no longer find the resources. Each...
20
by: C# Beginner | last post by:
I'm currently creating a database class, which contains a member called Open(). With this method users can open different databases. When a user tries to open a database which happens to be secured...
9
by: Mark Berry | last post by:
Hi, How can I determine whether an object is derived from another object? My specific example is that I have a CustomError class with several specific error types that derive from it...
0
by: Michael | last post by:
I know I am missing something simple, but I am stuck. When I submit the following for the employee info gets stored in scale1 and scale1 shows the employee number. Can someone show me my...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.