bound template parameter as argument to friend member functiondeclaration

J

Justin Miller

Ok, I tried to make that subject as descriptive as possible.

What I'm trying to do:

I'm attempting to use policies to create a generic memento (design
pattern) template. My Memento template so far is pretty simple:

using an idea of Andrei Alexandrescu (at least that's where I first read
it) to create a lightweight way of overloading member functions since
member function specialization is not possible.

template <typename T>
struct Type2Type {
typedef T OriginalType;
};

template <typename Originator,
typename CmdObj,
typename StorageType>
class Memento
{
public:
friend Memento Originator::CreateMemento(Type2Type<CmdObj>);
//other junk
};

My point in doing this is to force a compile-time check that Originator
has a CreateMemento function that takes an argument of type Type2Type<T>.
The main reason I decided to make just the member function CreateMemento a
friend is because a statement like this:

friend class Originator; //or this...
friend Originator;

is illegal in c++. If it's an entire class we're making a friend, the
friend syntax specifies that you have to include the word 'class.'
However, in this case, adorning the template parameter Originator, with
the word 'class,' is illegal (I forget the exact reason, but regardless,
not the point).

The problem:

I instantiate this template like this:

typedef Memento<DataContainer, DataCmdObj, std::vector<SpectralData*> >
DataMemento;

When I compile this with Sun Workshop 7, it results in an error, saying
that in the friend declaration above:

friend Memento Originator::CreateMemento(Type2Type<CmdObj>);

CmdObj is not defined. This really doesn't seem like it should be a
problem. Any thoughts here?!

Could it be a problem with forward declarations vs. the need for the whole
interface to be visible?

This has been bugging me big time, so any help is appreciated.

Justin

-----------------------------------------

Programmer/Analyst
NASA/Goddard Space Flight Center Code 660
email: (e-mail address removed)
office: 301-286-9261
 
T

Tom Widmer

When I compile this with Sun Workshop 7, it results in an error, saying
that in the friend declaration above:

friend Memento Originator::CreateMemento(Type2Type<CmdObj>);

CmdObj is not defined. This really doesn't seem like it should be a
problem. Any thoughts here?!

Could it be a problem with forward declarations vs. the need for the whole
interface to be visible?

This compiles fine on Comeau and GCC:

#include <vector>

template <typename T>
struct Type2Type {
typedef T OriginalType;
};

template <typename Originator,
typename CmdObj,
typename StorageType>
class Memento
{
public:
friend Memento Originator::CreateMemento(Type2Type<CmdObj>);
//other junk
};

class DataCmdObj;
class SpectralData;
struct DataContainer
{
Memento<DataContainer, DataCmdObj, std::vector<SpectralData*> >
CreateMemento(Type2Type<DataCmdObj>){ return
Memento<DataContainer, DataCmdObj, std::vector<SpectralData*> >(); }
};

int main()
{
Memento<DataContainer, DataCmdObj, std::vector<SpectralData*> >
DataMemento;
}

I believe that Sun's compiler isn't quite as good compliance-wise as
the latest efforts of its rivals...

Tom
 
J

Justin Miller

Yeah, we've tested on gcc as well, and agreed, it does compile fine.
Unfortunately, we have to support SUN as well - even though it seems to
be causing more and more problems for us. I wish we could just scrap that
compiler altogether, or upgrade to the latest version. We're still
supporting workshop 6! We've had a lot of standard-compliance issues.

Any thoughts about a workaround for this?

Justin

-----------------------------------------

Programmer/Analyst
NASA/Goddard Space Flight Center Code 660
email: (e-mail address removed)
office: 301-286-9261
 
T

Tom Widmer

Yeah, we've tested on gcc as well, and agreed, it does compile fine.
Unfortunately, we have to support SUN as well - even though it seems to
be causing more and more problems for us. I wish we could just scrap that
compiler altogether, or upgrade to the latest version. We're still
supporting workshop 6! We've had a lot of standard-compliance issues.

Any thoughts about a workaround for this?

I'm afraid I don't have sun CC to experiment with, so not really. Does
it compile ok if DataCmdObj is a completely defined type? How about if
you change your check to something like:

template <typename Originator,
typename CmdObj,
typename StorageType>
class Memento
{
private:
static Type2Type<CmdObj> makeType2TypeCmdObj();
static Originator makeOriginator();
static char takesMemento(Memento const&);

static int const check =
sizeof(

takesMemento(makeOriginator().CreateMemento(makeType2TypeCmdObj()))
) == 1;

public:
//etc.
};

Tom
 
J

Justin Miller

Mmmm. This is an almost perfect solution for me. It certainly enforces
the policy, however, I still need for ONLY the CreateMemento function
of the Originator to be able to access the private members of the
Memento object. Any way for that to happen?

The friend declaration would have been perfect (but Sun is stupid).
One could do it Java style by making a new (possibly nested) memento
class for each command that needs one. I was hoping to avoid this by
using the template (maybe I was being overly optimistic, thinking that
a memento would only need to store one data type... could be extended
to two types w/ little difficulty).

Excellent suggestion though. I may end up using parts of it.

Justin
 

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,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top