Having a design program

R

REH

As I posted last week, I updated my C++ library to include a variant record
class. While using it in some code, I'm finding it would be convenient to
have a method that would basically say to the class object, "I don't care
what type of object you currently contain, but I know it is convertible to
T, so do it." Basically, I want a class member like:

template<class T>
T convert_to() const;

So, if I had a variant_record defined as such:

typedef variant_record<short, int, long> record;
record r = 1;

regardless of what it contains, I could say:

long v = r.convert_to<long>();

Currently, I would have to do something like this:

switch(r.get_type())
{
case record::type<short>::id:
v = r.get<short>();
break;
case record::type<int>::id:
v = r.get<int>();
break;
case record::type<long>::id:
v = r.get<long>();
break;
}

Now, I know in this case, I could simplify thing by just storing short and
int values in a long, but this is just an example.

I thought about this implementation:

template<class T>
T convert_to() const
{
switch (m_type)
{
case t1: return T(get<T1>());
case t2: return T(get<T2>());
case t3: return T(get<T3>());
case t4: return T(get<T4>());

// etcetera
}

The problem with this is the compiler would complain for the cases were one
of the types has no conversion to T.

I also thought about having each case call a static member of a template
structure with a bool template parameter and specialize on false if there is
not conversion. Something like:

template<class To, class From, bool B>
struct convert_helper {
static To convert(const From& f) {return To(f);}
};

template<class To, class From>
struct convert_helper<To, From, false> {
static To convert(const From& f) {throw invalid_variant_access();}
};

And then create a template "is_convertible" to determine if a cast is
possible. The problem here is (I think) it is not possible for
"is_convertible" to detect explicit casts, only implicit ones.

Anyone have any ideas how I can accomplish this?

Thanks,

REH
 
T

Thomas Matthews

REH said:
As I posted last week, I updated my C++ library to include a variant record
class. While using it in some code, I'm finding it would be convenient to
have a method that would basically say to the class object, "I don't care
what type of object you currently contain, but I know it is convertible to
T, so do it." Basically, I want a class member like:

template<class T>
T convert_to() const;

So, if I had a variant_record defined as such:

typedef variant_record<short, int, long> record;
record r = 1;

regardless of what it contains, I could say:

long v = r.convert_to<long>();

Currently, I would have to do something like this:

switch(r.get_type())
{
case record::type<short>::id:
v = r.get<short>();
break;
case record::type<int>::id:
v = r.get<int>();
break;
case record::type<long>::id:
v = r.get<long>();
break;
}

Now, I know in this case, I could simplify thing by just storing short and
int values in a long, but this is just an example.

I thought about this implementation:

template<class T>
T convert_to() const
{
switch (m_type)
{
case t1: return T(get<T1>());
case t2: return T(get<T2>());
case t3: return T(get<T3>());
case t4: return T(get<T4>());

// etcetera
}

The problem with this is the compiler would complain for the cases were one
of the types has no conversion to T.

I also thought about having each case call a static member of a template
structure with a bool template parameter and specialize on false if there is
not conversion. Something like:

template<class To, class From, bool B>
struct convert_helper {
static To convert(const From& f) {return To(f);}
};

template<class To, class From>
struct convert_helper<To, From, false> {
static To convert(const From& f) {throw invalid_variant_access();}
};

And then create a template "is_convertible" to determine if a cast is
possible. The problem here is (I think) it is not possible for
"is_convertible" to detect explicit casts, only implicit ones.

Anyone have any ideas how I can accomplish this?

Thanks,

REH

Variant records are such the nightmare.

The case in point: assignment.
One has to allow assignment between variant records of
the same type, but not allow assignment between variant
records of different types.

Last time I researched this, I was using the Visitor
pattern along with double-dispatch to handle type safe
assignment. I want to be able to assign generic "fields"
to each other without knowing the types. {This occurs
when copying generic records.} Such the nightmare.

My solution was to have a base class which defines
operator=() as throwing an exception. Descendant
classes are encouraged to provide their own assignment
operators. Any base classes in the middle must throw
exceptions for their assignment operators.

This was just assignment. Equality is another headache.
And you want type conversion. Don't come walking my
way with this.

Perhaps remembering Scott Meyer's discussion that
public functions may increase encapsulation will help.
I.e. Function(MyObject& obj) vs obj.Function().


--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
http://www.comeaucomputing.com/learn/faq/
Other sites:
http://www.josuttis.com -- C++ STL Library book
http://www.sgi.com/tech/stl -- Standard Template Library
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,802
Messages
2,569,662
Members
45,433
Latest member
andrewartemow

Latest Threads

Top