C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Defining conversion operators at run-time

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Edd
Guest





PostPosted: Tue Nov 08, 2005 10:44 am    Post subject: Defining conversion operators at run-time Reply with quote



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 Smile
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





PostPosted: Thu Nov 17, 2005 12:04 am    Post subject: Re: Defining conversion operators at run-time Reply with quote



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
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
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


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.