 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Edd Guest
|
Posted: Tue Nov 08, 2005 10:44 am Post subject: Defining conversion operators at run-time |
|
|
Hello all,
I've recently been looking at various implementations for opaque types and
'simulated unions' and toying with some ideas of my own. Along the way, when
thinking about conversions for these types, I found myself thinking "I wonder
what happens if I created a templated conversion operator...?". Like a moth to a
flame I began experimenting and I've come up with a peculiar little class that
lets one 'define' conversion operators to arbitrary types at /run-time/.
I don't really know what to make of it. It's 'cute', but I'm not sure whether I
like it or not or even if it's useful! I'd be interested to hear what the keen
minds here think of it, whether their opinions be damning or otherwise.
Ok, so here's the code. Hopefully it's compilable for you (I'm on MinGW g++
3.4.2 and passed Comeau online). Test driver/example is at the end -- might be a
good idea to look at that first to see what I'm on about. I've also put my
original source files here:
http://www.nunswithguns.net/guff/core/shared.h
http://www.nunswithguns.net/guff/core/ptr.h
http://www.nunswithguns.net/guff/core/conv.h
http://www.nunswithguns.net/guff/core/convtest.cpp
//START OF CODE
#include <map>
#include <typeinfo>
#include <vector>
#include <iostream>
#include <ostream>
#include <iterator>
#include <algorithm>
//replaced with naked pointers for NG post, please excuse leaks!
//#include "ptr.h"
namespace core
{
template<typename FROM>
class conv
{
private:
struct worker_base
{
virtual ~worker_base() { }
virtual void convert(const FROM &src, void *tgt) const = 0;
};
template<typename TO, typename FUNCTOR>
struct worker : public worker_base
{
worker(const FUNCTOR &f) : f_(f) { }
void convert(const FROM &src, void *tgt) const
{
f_(src, *static_cast<TO *>(tgt));
}
FUNCTOR f_;
};
/*typedef std::map< const std::type_info*, core::ptr
conv_map; */
typedef std::map< const std::type_info*, worker_base* > conv_map;
const FROM *source_;
static conv_map funcs_;
protected:
conv(const FROM &source) : source_(&source) { }
template<typename TO, typename FUNCTOR>
static void add_conversion(FUNCTOR f)
{
funcs_[&typeid(TO)] = new worker<TO, FUNCTOR>(f);
}
template<typename TO>
static void rem_conversion()
{
funcs_.erase(&typeid(TO));
}
public:
template<typename TO> operator TO() const throw(std::bad_cast)
{
typename conv_map::const_iterator p = funcs_.find(&typeid(TO));
if(p == funcs_.end()) throw std::bad_cast();
TO target; //implies default constructor requirement
p->second->convert(*source_, &target);
return target;
}
};
template<typename T> typename conv<T>::conv_map conv<T>::funcs_;
} //close core namespace
class satanic : public core::conv<satanic>
{
public:
satanic(int i) : core::conv<satanic>(*this), i_(i) { }
int get() const { return i_; }
using core::conv<satanic>::add_conversion;
using core::conv<satanic>::rem_conversion;
private:
int i_;
};
void convert_to_vector(const satanic &source, std::vector<int> &target)
{
target.clear();
target.assign(3, source.get());
}
int main()
{
satanic n(6);
satanic::add_conversion< std::vector(convert_to_vector);
//we can now convert from a satanic to a vector<int> !!!
std::vector<int> sss = n;
//cerr glows red appropriately in my console
std::copy(sss.begin(), sss.end(), std::ostream_iterator<int>(std::cerr));
std::cerr << std::endl;
return 0;
}
//END OF CODE
Anyone?
Edd
--
Edd Dawson www.nunswithguns.net | "It's sad when someone you know
To email me, cut the crap. | becomes someone you knew."
[email]edd (AT) nunswithcrapguns (DOT) net[/email] | - Henry Rollins
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
elazro Guest
|
Posted: Thu Nov 17, 2005 12:04 am Post subject: Re: Defining conversion operators at run-time |
|
|
I think it's important to point out that in a sense, you aren't really
adding new conversion operators at runtime - you are just adding the
conversion actions. The operators are instantiated (at compile-time)
whenever you try to perform a conversion - i.e. if you comment out the
2nd line of main (the 'add_conversion') it still compiles, but will
throw a std::bad_cast when run.
The technique of overloading the conversion operator is a bit
dangerous, as it destroys compile-time type checking. However, it can
have its uses - I've used this technique to create a 'Nugget' class,
which is a type that can hold a value of any type. This is much like
boost::any (which I discovered later, and will probably use from now
on) except that boost::any does not provide a conversion operator - you
must use boost::any_cast<TO>(). While I haven't experienced any major
problems with the templated conversion operators in my nugget class, I
do use it in a pretty limited context, and I imagine the boost
maintainers chose the any_cast route to avoid any problems.
-matt
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|