By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
458,081 Members | 1,317 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 458,081 IT Pros & Developers. It's quick & easy.

bound template parameter as argument to friend member functiondeclaration

P: n/a
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: mi*****@milkyway.gsfc.nasa.gov
office: 301-286-9261

Jul 22 '05 #1
Share this Question
Share on Google+
4 Replies


P: n/a
On Mon, 1 Nov 2004 17:13:55 -0500, Justin Miller
<mi*****@milkyway.gsfc.nasa.gov> wrote:
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
Jul 22 '05 #2

P: n/a
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: mi*****@milkyway.gsfc.nasa.gov
office: 301-286-9261

On Tue, 2 Nov 2004, Tom Widmer wrote:

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


Jul 22 '05 #3

P: n/a
On Tue, 2 Nov 2004 09:00:47 -0500, Justin Miller
<mi*****@milkyway.gsfc.nasa.gov> wrote:
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(makeTy pe2TypeCmdObj()))
) == 1;

public:
//etc.
};

Tom
Jul 22 '05 #4

P: n/a
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
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(makeTy pe2TypeCmdObj()))
) == 1;

public:
//etc.
};

Tom

Jul 22 '05 #5

This discussion thread is closed

Replies have been disabled for this discussion.