Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Polymorphism (without virtual functions) with a method template.

Reply
Thread Tools

Polymorphism (without virtual functions) with a method template.

 
 
Belebele
Guest
Posts: n/a
 
      12-11-2007
Suppose that I want to write a (concrete) interface class (without
virtual functions) to classes that contain a method template

// --------------------------------------
class Interface {
public:
template <typename Wrapped>
Interface(Wrapped& );
// wraps a reference to another object
// that implements the method template

template <typename T>
bool foo(T ); // forwards the call to the wrapped object
};
// --------------------------------------

and then use it:

// --------------------------------------
class Bar {
public:
template <typename T>
bool foo(T );
};

....
Bar b;
Interface i(b);
// --------------------------------------


The problem is that I don't know how to implement this. I know how to
implement it without method templates (with table of function
pointers).

Any idea how to do it?

Thanks.
 
Reply With Quote
 
 
 
 
Ondra Holub
Guest
Posts: n/a
 
      12-11-2007
On 11 Pro, 13:58, Belebele <(E-Mail Removed)> wrote:
> Suppose that I want to write a (concrete) interface class (without
> virtual functions) to classes that contain a method template
>
> // --------------------------------------
> class Interface {
> public:
> template <typename Wrapped>
> Interface(Wrapped& );
> // wraps a reference to another object
> // that implements the method template
>
> template <typename T>
> bool foo(T ); // forwards the call to the wrapped object};
>
> // --------------------------------------
>
> and then use it:
>
> // --------------------------------------
> class Bar {
> public:
> template <typename T>
> bool foo(T );
>
> };
>
> ...
> Bar b;
> Interface i(b);
> // --------------------------------------
>
> The problem is that I don't know how to implement this. I know how to
> implement it without method templates (with table of function
> pointers).
>
> Any idea how to do it?
>
> Thanks.


I am not sure if I understood exactly what you need. If you want to
store value of some templated type, you have to make the whole class
templated (because the Wrapped type and value must be accessible from
constructor as well as from method foo).

// --------------------------------------
template<typename Wrapped>
class Interface {
public:
Interface(Wrapped& w): w_(w) { }
// wraps a reference to another object
// that implements the method template

template <typename T>
bool foo(T& t) // forwards the call to the wrapped object
{
w_.foo(t);
}

private:
Wrapped& w_;
};

// --------------------------------------

and then use it:

// --------------------------------------
class Bar {
public:
template <typename T>
bool foo(T );

};

....
Bar b;
Interface<Bar> i(b);
// --------------------------------------

 
Reply With Quote
 
 
 
 
Belebele
Guest
Posts: n/a
 
      12-11-2007
> I am not sure if I understood exactly what you need. If you want to
> store value of some templated type, you have to make the whole class
> templated


That's not what I want. I want the Interface class to be a class, not
a class template. That way, I could potentially assign to an object of
the Interface class any object that implements the desired interface.
That is:

class B1 {
public:
template <typename T>
void foo(T );
};

class B2 {
public:
template <typename T>
void foo(T );
};

B1 b1;
Interface i(b1);
i.foo(1);

B2 b2;
i = b2;
i.foo(1);


This is simple to implement if the interface does not contain method
templates. I am lost when method templates are involved.
 
Reply With Quote
 
Ondra Holub
Guest
Posts: n/a
 
      12-11-2007
On 11 Pro, 20:58, Belebele <(E-Mail Removed)> wrote:
> > I am not sure if I understood exactly what you need. If you want to
> > store value of some templated type, you have to make the whole class
> > templated

>
> That's not what I want. I want the Interface class to be a class, not
> a class template. That way, I could potentially assign to an object of
> the Interface class any object that implements the desired interface.
> That is:
>
> class B1 {
> public:
> template <typename T>
> void foo(T );
>
> };
>
> class B2 {
> public:
> template <typename T>
> void foo(T );
>
> };
>
> B1 b1;
> Interface i(b1);
> i.foo(1);
>
> B2 b2;
> i = b2;
> i.foo(1);
>
> This is simple to implement if the interface does not contain method
> templates. I am lost when method templates are involved.


I think it is not possible. You have to store the reference to other
class instance, so the referenced class would have to be derived from
some common class. It is hard to combine template polymorphism and
class polymorphism.
 
Reply With Quote
 
Jonathan Mcdougall
Guest
Posts: n/a
 
      12-11-2007
On Dec 11, 2:58 pm, Belebele <(E-Mail Removed)> wrote:

I am including your original Interface class here for
reference.

> class Interface {
> public:
> template <typename Wrapped>
> Interface(Wrapped& );
> // wraps a reference to another object
> // that implements the method template
>
> template <typename T>
> bool foo(T ); // forwards the call to the wrapped
> // object
> };


For Interface to be able to keep a reference to the wrapped
object, it needs to store it somewhere. Therefore, it needs
to have a member object of an arbitrary type, namely T.
Conclusion: Interface needs to be a class template.

> That's not what I want. I want the Interface class to be a
> class, not a class template. That way, I could potentially
> assign to an object of the Interface class any object that
> implements the desired interface. That is:


One does not prevent the other. Look again at the example you
were given in http://tinyurl.com/2rppm8. It corresponds to the
problem you are explaining.

> class B1 {
> public:
> template <typename T>
> void foo(T );
>
> };
>
> class B2 {
> public:
> template <typename T>
> void foo(T );
>
> };
>
> B1 b1;
> Interface i(b1);
> i.foo(1);
>
> B2 b2;
> i = b2;
> i.foo(1);
>
> This is simple to implement if the interface does not
> contain method templates. I am lost when method templates
> are involved.


I don't see how this can be "simple to implement", except by
using function pointers, which is not particularily simple,
safe or fun to play with.

You have two important requirements:

1) Wrapped classes do not derive from a common base class.
Therefore, you need the wrapper class to be templated.

2) Some member functions in the wrapped classes are templated.
Therefore, you need the wrapper class to have as many
templated member functions.

--
Jonathan Mcdougall
 
Reply With Quote
 
Belebele
Guest
Posts: n/a
 
      12-11-2007
> I don't see how this can be "simple to implement", except by
> using function pointers, which is not particularily simple,
> safe or fun to play with.


See Listing 1 on http://www.ddj.com/cpp/184401848 Yep, function
pointers to the rescue. Nothing really too extraordinary.

The method template requirement is what puzzles me.

I would prefer not having to force the Wrapped objects to derive (in
my case artificially) from a base class.
 
Reply With Quote
 
Jonathan Mcdougall
Guest
Posts: n/a
 
      12-12-2007
On Dec 11, 5:48 pm, Belebele <(E-Mail Removed)> wrote:
> > I don't see how this can be "simple to implement",
> > except by using function pointers, which is not
> > particularily simple, safe or fun to play with.

>
> See Listing 1 on http://www.ddj.com/cpp/184401848. Yep,
> function pointers to the rescue. Nothing really too
> extraordinary.


I copy the listing (with some corrections) for the sake of the
discussion:

# include <iostream>

struct AbcFuBar
{
virtual ~AbcFuBar()
{
}

virtual void FuBar() = 0;
};

struct BaseFuBar : public AbcFuBar
{
void FuBar()
{
std::cout << "BaseFuBar";
}
};

struct DerivedFuBar : public BaseFuBar
{
void FuBar()
{
std::cout << "DerivedFuBar";
}
};

int main()
{
DerivedFuBar d;
BaseFuBar& b = d;
AbcFuBar& a = b;
a.FuBar(); // output DerivedFuBar
}

This example does not correspond to your original post. It
only demonstrates the use of inheritance and virtual
functions.

> The method template requirement is what puzzles me.
>
> I would prefer not having to force the Wrapped objects
> to derive (in my case artificially) from a base class.


Basically, you need templates if you don't have a base class.
Otherwise, what will be the type of the member object of your
"Interface" class?

class wrapper
{
public:
template <class T>
wrapper(T& t)
: t_(t)
{
}

private
??? t_;
};

Note that you cannot replace ??? by T, since it only exists in
the constructor. To do this, make wrapper a template:

template <class T>
class wrapper
{
public:
wrapper(T& t)
: t_(t)
{
}

private:
T t_;
};

in which case the constructor does not need to be templated
anymore (unless it should accept things that are not Ts).

Now, if you want to call member functions on the wrapped
oject, you need to know the function names along with the type
and numbers of parameters they take.

template <class T>
class wrapper
{
public:
wrapper(T& t)
: t_(t)
{
}

void f(int i)
{
t_.f(i);
}

private:
T t_;
};

class bar
{
public:
void f(int i)
{
}
};

int main()
{
bar b;
wrapper<bar> w(b);

w.f(0);
}

To remove the "hardcoded" type information in f(), you can use
templates:

template <class T>
class wrapper
{
public:
wrapper(T& t)
: t_(t)
{
}

template <class P1>
void f(P1 p1)
{
t_.f(p1);
}

private:
T t_;
};

--
Jonathan Mcdougall
 
Reply With Quote
 
naoki
Guest
Posts: n/a
 
      12-13-2007
On Dec 11, 7:38 pm, Ondra Holub <(E-Mail Removed)> wrote:
> On 11 Pro, 20:58, Belebele <(E-Mail Removed)> wrote:
>
>
>
> > > I am not sure if I understood exactly what you need. If you want to
> > > store value of some templated type, you have to make the whole class
> > > templated

>
> > That's not what I want. I want the Interface class to be a class, not
> > a class template. That way, I could potentially assign to an object of
> > the Interface class any object that implements the desired interface.
> > That is:

>
> > class B1 {
> > public:
> > template <typename T>
> > void foo(T );

>
> > };

>
> > class B2 {
> > public:
> > template <typename T>
> > void foo(T );

>
> > };

>
> > B1 b1;
> > Interface i(b1);
> > i.foo(1);

>
> > B2 b2;
> > i = b2;
> > i.foo(1);

>
> > This is simple to implement if the interface does not contain method
> > templates. I am lost when method templates are involved.

>
> I think it is not possible. You have to store the reference to other
> class instance, so the referenced class would have to be derived from
> some common class. It is hard to combine template polymorphism and
> class polymorphism.


Do this help you?

#include <string>
#include <iostream>

struct Interface {
template<typename T>
void foo(T& t) {
t.foo("foo()");
}
};

class A {
public:
void foo(const std::string& parameter) {
std::cout << "A::foo( " + parameter + " )" << std::endl;
}
};

class B {
public:
void foo(const std::string& parameter) {
std::cout << "B::foo( " + parameter + " )" << std::endl;
}
};

int main() {
Interface i;
A a;
B b;
i.foo(a);
i.foo(b);
}

But if you need to store the class reference passing it on Interface
class constructor it is not possible unless you declare Interface as a
class template.
 
Reply With Quote
 
naoki
Guest
Posts: n/a
 
      12-13-2007
On Dec 11, 5:58 pm, Belebele <(E-Mail Removed)> wrote:
> > I am not sure if I understood exactly what you need. If you want to
> > store value of some templated type, you have to make the whole class
> > templated

>
> That's not what I want. I want the Interface class to be a class, not
> a class template. That way, I could potentially assign to an object of
> the Interface class any object that implements the desired interface.
> That is:
>
> class B1 {
> public:
> template <typename T>
> void foo(T );
>
> };
>
> class B2 {
> public:
> template <typename T>
> void foo(T );
>
> };
>
> B1 b1;
> Interface i(b1);
> i.foo(1);
>
> B2 b2;
> i = b2;
> i.foo(1);
>
> This is simple to implement if the interface does not contain method
> templates. I am lost when method templates are involved.


Do this help you?

#include <string>
#include <iostream>

struct Interface {
template<typename T>
void foo(T& t) {
t.foo("foo()");
}

};

class A {
public:
void foo(const std::string& parameter) {
std::cout << "A::foo( " + parameter + " )" <<
std::endl;
}

};

class B {
public:
void foo(const std::string& parameter) {
std::cout << "B::foo( " + parameter + " )" <<
std::endl;
}

};

int main() {
Interface i;
A a;
B b;
i.foo(a);
i.foo(b);

}

But if you need to store the class reference passing it on Interface
class constructor it is not possible unless you declare Interface as a
class template.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Dynamic polymorphism vs. Static polymorphism Krivenok Dmitry C++ 13 06-01-2006 09:49 AM
I see no difference in an inheirited non-virtual method and an inheirited virtual method jlopes C++ 7 11-19-2004 07:47 PM
virtual assignment operator/polymorphism question Stephan Kurpjuweit C++ 3 06-14-2004 06:19 PM
virtual function and polymorphism john sun C++ 6 01-22-2004 08:49 PM
polymorphism - virtual function al C++ 7 01-01-2004 10:29 AM



Advertisments