Tricky partial constructor specialization

  • Thread starter daniel.w.gelder
  • Start date
D

daniel.w.gelder

Hello, I have a template with two typenames.

template <typename BASE, typename SUPER> struct Morphic
{
Morphic<BASE,SUPER>( ) { .. }
~Morphic<BASE,SUPER>( ) { .. }
};

Morphic takes a Base and a Super. Sometimes Super is itself a Morphic.
In that situation i allow a Morphic<BASE,SUPER> to be constructed from
any Morphic which uses Morphic<BASE,SUPER> as its own SUPER. I do it
like this:

template <typename S1>
Morphic<BASE,SUPER>(const Morphic<S1, Morphic<BASE,SUPER> >& copy)
{ .. }

In other words:

typedef Morphic<long, void> LongMorphic;
typedef Morphic<long, LongMorphic> LongerMorphic;

LongerMorphic hello();
LongMorphic hola(hello); // can be constructed.

I also allow construction from Morphics that are 2 or more levels
removed:

template <typename S1, typename S2>
Morphic <BASE,SUPER>(const Morphic <S2, Morphic <S1, Morphic
<BASE,SUPER> > >& copy) { .. }

Etc...so you can construct a Morphic<A,B> from a Morphic<Q, Morphic<Z,
Morphic<A,B> > >.

What I am attempting now is the reverse: construction of Morphic<Q,
Morphic<Z, Morphic<A,B> > > from Morphic<A,B>. If the compiler
understood what I meant, I would try this syntax:

template <typename S1>
Morphic<S1, Morphic<BASE,SUPER> >(const Morphic<BASE,SUPER>& copy)

Now of *course* I have two solutions already but neither is good. First
I can simply accept SUPER as a parameter:

Morphic<BASE,SUPER>(const SUPER& copy)

Works but doesn't scale to more than one level -- I can construct
Morphic<Z, Morphic<A,B> > from Morphic<A, B>, but I can't construct
Morphic<Q, Morphic<Z, Morphic<A,B> > > from Morphic<A,B>.

Another solution is to make a different implementation of the template
for each situation:

template <typename BASE, typename SUPER> Morphic;
template <typename BASE>
Morphic<BASE, void> { .. }
template <typename BASE, typename BASE2>
Morphic<BASE, Morphic<BASE2, void> > { .. }
template <typename BASE, typename BASE2, typename BASE3>
Morphic<BASE, Morphic<BASE2, Morphic<BASE3, void> > > { .. };

And have every implementation support the extent that it is. But that
seems wasteful to solve a syntax issue.

Anyone have any ideas? I'm still pretty new to metaprogramming so...:)

Thanks in advance.
Dan
 
B

ben

The major problem, if I understand you well, is that C++ doesn't support
template function specialization. But this can be easily achieved by
factoring out the specializing part to a standalone class. So instead of
doing

template <typename BASE, typename SUPER>
class Morphic;

template <typename NonMorphic>
class MorphicContructor{};

template <typename TMorphic>
class MorphicConstructor
{
public:
template <typename T>
static void Construct(TMorphic& morphic, const T&);
};

template <typename BASE, typename SUPER, typename S1>
class MorphicConstructor<Morphic<S1, Morphic<BASE, SUPER> > >
{
public:
static void Construct(
Morphic<S1, Morphic<BASE, SUPER> >& morphic,
const Morphic<BASE, SUPER>& copy);
};

template <typename BASE, typename SUPER>
class Morphic
{
public:
template <typename T>
Morphic(const T& copy)
{
MorphicConstructor::Construct(*this, copy);
}
};
 
S

Samee Zahur

template said:
{
Morphic<BASE,SUPER>( ) { .. }
~Morphic<BASE,SUPER>( ) { .. }
};
You shouldn't have to retype the tempate params - Morphic(){...} and
~Morphic(){...} should be good enough.

I really have no idea as to why you need classes like these (specially
passing void types into parameters), but the first thing you should do
with these constructors is to make them explicit - since implicit
conversion will fail anyway due to ambiguity. And to make this work,
there is this one thing you might try, although I'm not sure about it's
success:

template <typename Base2,typename Super2>
explicit Morphic(const Morphic<Base2,Super2>& copy)
{
//...
}

template <typename Base2,typename BaseInner,typename Super2>
explicit Morphic(const Morphic<Base2,Morphic<BaseInner,Super2> >& copy)
{
//...
//Call the inner morphic somewhere, making a temporary object
Morphic<BaseInner,Super>(); //Will fail compilation if it doesn't
find
// a matched constructor, enforcing your
rules
}

Samee
 
D

daniel.w.gelder

I had never heard of "explicit" before but it did do the trick of
putting the problem next to the offending line. This group is the
greatest ever.

For those interested, I used my original system for downcasting, and a
combination of both for upcasting. I thought having two systems would
cause ambiguity but xCode seems to have no problem.

By the way, I started a yahoo group for my project. It's
groups.yahoo.com/group/dgic. It's kind of a Tiny Template Library, but
oriented towards syntax sugar instead of towards a bunch of really
complicated features you don't use.

Thanks
Dan
 
B

ben

template frenzy!
I just wanted to solve the OP's problem, I did it.

And yes, I am template-maniac, because it is cool and fun! : )

ben
 

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

No members online now.

Forum statistics

Threads
474,294
Messages
2,571,507
Members
48,193
Latest member
DannyRober

Latest Threads

Top