private overloading

D

daniel.w.gelder

Hello, I am writing some code that converts one group of old obselete
classes to another newer group, like this:

Bag Convert(OldBag* b) { return Bag(b->x, b->y); }
Shag Convert(OldShag* b) { return Shag(b->z * b->m); }
Rag Convert(OldRag* b) { return Rag(); }

The conversion process is pretty simple, so it's advantageous to just
have one simple syntax like Convert(this), it helps make the code
easier to read .. i can just Convert(this) and not worry about it. I
would like to make the constructors of the new Bag, Shag, Rag, etc,
protected or private though for various reasons, which means the C
functions couldn't access them. I could make Convert an overloaded
member function of a utility class, and then have it as friends of Bag
Shag Rag, as one solution. But I would like to keep the conversion
prototypes with their classes. Is there a partial specialization
template solution? Some thing like

class Convertor
{
template <typename Old, typename New>
New Convert(Old* n);
}

And then I specialize in different places in different headers:

template <> Bag Convert(OldBag* b) { return Bag(b->x, b->y); }
// later..
template <> Shag Convert(OldShag* b) { return Shag(b->m*b->z); }
// later..
template <> Rag Convert(OldRag* b) { return Rag(); }

As you can see I'm not good with the template syntax. I just want to be
able to define overloaded functions in lots of different places in the
project.

Thanks much.

Dan
 
D

daniel.w.gelder

Rats! On further building it turns out I can't even do it the first
way, because the linker thinks Convert is multiply-defined from being
included in several places.
 
V

Victor Bazarov

Hello, I am writing some code that converts one group of old obselete
classes to another newer group, like this:

Bag Convert(OldBag* b) { return Bag(b->x, b->y); }
Shag Convert(OldShag* b) { return Shag(b->z * b->m); }
Rag Convert(OldRag* b) { return Rag(); }

The conversion process is pretty simple, so it's advantageous to just
have one simple syntax like Convert(this), it helps make the code
easier to read .. i can just Convert(this) and not worry about it. I
would like to make the constructors of the new Bag, Shag, Rag, etc,
protected or private though for various reasons, which means the C
functions couldn't access them. I could make Convert an overloaded
member function of a utility class, and then have it as friends of Bag
Shag Rag, as one solution. But I would like to keep the conversion
prototypes with their classes. Is there a partial specialization
template solution? Some thing like

class Convertor
{
template <typename Old, typename New>
New Convert(Old* n);
}

And then I specialize in different places in different headers:

template <> Bag Convert(OldBag* b) { return Bag(b->x, b->y); }
// later..
template <> Shag Convert(OldShag* b) { return Shag(b->m*b->z); }
// later..
template <> Rag Convert(OldRag* b) { return Rag(); }

As you can see I'm not good with the template syntax. I just want to be
able to define overloaded functions in lots of different places in the
project.

From the second posting you mentioned you have a problem with multiple
definitions of the same function. Easy to prevent. Declare them all
'inline'.

Now, back to the question at hand. You forgot a semicolon after the
'Convertor' class definition. I will consider it a typo. The syntax for
the specialisations should be

template<> RVT Convertor::Convert<T,RVT>(T *p) ...

, replace "RVT" with the proper return value type and "T" with the proper
argument class name.

V
 
D

daniel.w.gelder

I'm using inline for the present; the linker's happy.

class Rug
{
};
class OldRug
{
};

class Tool
{
public:
template <typename OLD, typename NEW>
NEW Convert(OLD old);
};

template <>
Rug Tool::Convert<OldRug, Rug>(OldRug old)
{
Rug rug;
return rug;
}

void TryIt();
void TryIt()
{
Tool tool;
OldRug oldRug;
Rug rug;

rug = tool.Convert(oldRug);
}

Metrowerks says:
Error : function call '[Tool].Convert({lval} OldRug)' does not match
'Tool::Convert<...>(__T0)' (non-static)
Morphic.cpp line 71 rug = tool.Convert(oldRug);

Using tool.Convert<OldRug, Rug>(oldRug) directly works of course, but
this is not overloading.

As a side note, do some compilers have trouble with spreading templates
across multiple header files...is that against the C++ standard?

Thanks, thanks, thanks

Dan
 
V

Victor Bazarov

I'm using inline for the present; the linker's happy.

class Rug
{
};
class OldRug
{
};

class Tool
{
public:
template <typename OLD, typename NEW>
NEW Convert(OLD old);
};

template <>
Rug Tool::Convert<OldRug, Rug>(OldRug old)
{
Rug rug;
return rug;
}

void TryIt();
void TryIt()
{
Tool tool;
OldRug oldRug;
Rug rug;

rug = tool.Convert(oldRug);

It cannot determine both template arguments from only one function
argument.
}

Metrowerks says:
Error : function call '[Tool].Convert({lval} OldRug)' does not match
'Tool::Convert<...>(__T0)' (non-static)
Morphic.cpp line 71 rug = tool.Convert(oldRug);

Using tool.Convert<OldRug, Rug>(oldRug) directly works of course, but
this is not overloading.

Why not? Make your 'NEW' argument the first one and supply only that,
and the second should be picked up:

class Rug {};
class OldRug {};

struct Tool
{
template<class N, class O> N Convert(O);
};

template<>
Rug Tool::Convert<Rug, OldRug>(OldRug old)
{
return Rug();
}

void TryIt()
{
Tool tool;
OldRug oldRug;
Rug rug;

rug = tool.Convert<Rug>(oldRug); // overloading should work
}

As a side note, do some compilers have trouble with spreading templates
across multiple header files...is that against the C++ standard?

No.

V
 
D

daniel.w.gelder

rug = tool.Convert<Rug>(oldRug); // overloading should work

That compiles fine, but what I really want to do is not have to place
anything but the 'this' parameter in the code. Because I'm
building...shudder...a macro that converts 'this', whatever it is, to
the new type. Currently:

#define iMyself (Convert(this))

Don't worry, it's not commercial code.

Dan
 
V

Victor Bazarov

That compiles fine, but what I really want to do is not have to place
anything but the 'this' parameter in the code.

I am not sure I understand.

Let's go back to your original post. You need a tool which is going to
convert A,B,C to AA,BB,CC. You want all conversion methods to be picked
with overload resolution, with you providing only arguments. OK. So,
why don't you provide both arguments, then?

class Tool {
template<class To, class From> static void Convert(To*, From*);
};

template<> void Tool::Convert<AA,A>(AA* aa, A* a) {
// blahblah
}

....
AA::AA(A const * someA) {
Tool::Convert(this, someA);
}

Not sure it's what you need, but methinks it's the right direction.

V
 
D

daniel.w.gelder

I want to have the function accept only 'this' and return the
appropriate type, for the following reason: the 'new types' happen to
be nice refcounted autoptrs I just can't live without. (I'm going to
put the library on a web page when I'm done). I've got superterrific
macros for defining new stucts and declaring autoptr types all with a
single macro ... it's a dream scheme where you ++ the autoptrs to
initialize them and -- to release the reference and -> to get at the
refcounted ptr, and they support crazy polymorphic/translation stuff
too.

I've managed to develop it to the point where the base refcounted ptrs
are almost completely abstracted away and secret. You can't even write
C++ constructors for them, you have to use my system: Object++(...);
I'm deliberately enforcing a different syntax so your brain adjusts to
working differently.

The annoying part is 'this'. It's not horribly in the way, since you
can even use this-> for the same feeling as the objects. When a
function expects an Object and all you have is 'this', the system has
to wrap it back into its object type. One obvious way is to construct
the Object from the ptr:

Pigeon:: Pigeon(pigeon_base* base) {..}
pigeon_base::f()
{
Pigeon p = (this);
}

But (1) it is jarring to see C++ syntax in a system that hides it
everywhere else and (2) may shut me out from future expansion of the
typing system. So i'm trying to hide it in a macro for now:

#define Myself (_OVERLOADED_FUNCTION(this))
Pigeon p = Myself;

So, I need a function, class, template, something, anything, that takes
any kind of _base and returns the corresponding autoptr. Overloading a
global-level function, and putting invididual convertors into the
'define class' macro, seems to work just fine, so I'm going with it for
now. But the Pigeon constructor has to be public for that, which I
don't want because I want to ensure there's no way to hack the system.
So I was hoping to make some kind of overloaded class and declare it as
a friend of the constructor.

Sorry about the long post. You've been very helpful when I was obtuse
:)

Dan
 
?

??

So,if I really understand you, you
want something like this:

class Tool
{
public:
template <typename New,typename Old>
New Convert(Old*);
};

And then the whole bunch of specializations without
the need to tell the compiler about the return type.
Even though I don't understand why you would
ever go to such lengths "just for a different syntax"
(I think C++'s syntax is actually quite OK), perhaps
this is the one you want:

class Tool
{
public:
template <typename Old>
Old::New Convert(Old*);
};

Then you define the typedefs in the classes,
like

class OldBag
{
public:
typedef Bag New; // Smalltalk???
//the rest
};

class OldShag
{
public:
typedef Shag New;
//the rest
};

And specialize the hell out of the classes.

Hope this was helpful.
 
Õ

õá

Sorry,I forgot to add the right "typename"s where I should.But this should
be just a minor change.

P.S.
Why do you want to write
Object++ (/*smth*?) ?????????
 

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,202
Messages
2,571,057
Members
47,664
Latest member
RoseannBow

Latest Threads

Top