473,513 Members | 11,702 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

pure virtual template...

Hi there,

I don't think I'll be able to describe my issue correctly, so
instead I'll just give a pseudo C++ code I am struggling with.
Basically I am looking for a 'pure virtual template' function that I
would be able to declare in the base class (*).

Thanks for suggestions,
-Mathieu
(*)
struct Base
{
};

struct A : public Base
{
template <typename Tvoid foo() {}
};

struct B : public Base
{
template <typename Tvoid foo() {}
};

int main(int argc, char *argv[])
{
Base * base;
if( argc )
{
base = new A;
}
else
{
base = new B;
}
base->foo<int>();
return 0;
}

Oct 26 '07 #1
11 2724
On Oct 26, 2:19 pm, mathieu <mathieu.malate...@gmail.comwrote:
Hi there,

I don't think I'll be able to describe my issue correctly, so
instead I'll just give a pseudo C++ code I am struggling with.
Basically I am looking for a 'pure virtual template' function that I
would be able to declare in the base class (*).
Hum...without much satisfaction here is my temporary solution.
Hopefully you guys will suggest something not involving making the
base class be polymorphic...
#include <iostream>

struct Base
{
template <typename Tvoid foo() const;
int base;
virtual void bla() {}
};

struct A : public Base
{
template <typename Tvoid foo() const { std::cout << "A" <<
std::endl; }
double a;
};

struct B : public Base
{
template <typename Tvoid foo() const { std::cout << "B" <<
std::endl; }
float b;
};

template <typename T>
void Base::foo() const
{
const A * a = dynamic_cast<const A*>(this);
const B * b = dynamic_cast<const B*>(this);
if( a ) a->foo<T>();
else if( b ) b->foo<T>();
}

int main(int argc, char *argv[])
{
Base * base;
if( argc 1 )
{
base = new A;
}
else
{
base = new B;
}
base->foo<int>();
return 0;
}

Oct 26 '07 #2
mathieu wrote:
Hi there,

I don't think I'll be able to describe my issue correctly, so
instead I'll just give a pseudo C++ code I am struggling with.
Basically I am looking for a 'pure virtual template' function that I
would be able to declare in the base class (*).
As most compilers implement virtual method by means of virtual method tables,
declaring a template member virtual is not allowed (sorry that I cannot cite the
paragraph of the C++ standard). Were it not so, the size of the VMT table could
not be determined by the compiler (it cannot predict how many instantiations of
the template member could be needed in the following code). Thus templates and
virtual methods don't go together.
(*)
struct Base
{
};

struct A : public Base
{
template <typename Tvoid foo() {}
};

struct B : public Base
{
template <typename Tvoid foo() {}
};

int main(int argc, char *argv[])
{
Base * base;
if( argc )
{
base = new A;
}
else
{
base = new B;
}
base->foo<int>();
return 0;
}
I think you mixed up two more or less orthogonal concepts of the C++ programming
language: templates are used to reuse code where the logic is known at compile
time (that means you know exactly what your code will do when you compile the
code), whereas virtual methods are used to reuse code whose semantics will be
determined at run-time. If you know at compile time that each class A and B will
have a foo implementation with template parameter int, you may do the following:

struct Base
{
virtual void foo_int () = 0;
};

struct [A and likewise B] : public Base
{
template <typename Tvoid foo() {}
virtual void foo_int ()
{
foo<int();
}
};

int main(int argc, char *argv[])
{
:
base->foo_int();
return 0;
}

Note that there are two different resolution mechanisms involved: template
programming uses the determination with instantiation of a template function
should be used (the proper template argument is deduced), whereas virtual
methods employ a resolution mechanism involving VMTs: this table decides at
run-time which method should be invoked. You are trying to get both mechansims
working in a single step. For above mentioned reasons, this won't work.

Regards,
Stuart
Oct 26 '07 #3
On Oct 26, 1:49 pm, mathieu <mathieu.malate...@gmail.comwrote:
On Oct 26, 2:19 pm, mathieu <mathieu.malate...@gmail.comwrote:
Hi there,
I don't think I'll be able to describe my issue correctly, so
instead I'll just give a pseudo C++ code I am struggling with.
Basically I am looking for a 'pure virtual template' function that I
would be able to declare in the base class (*).

Hum...without much satisfaction here is my temporary solution.
Hopefully you guys will suggest something not involving making the
base class be polymorphic...

I have to say, I don't really see the problem or what you're hoping to
achieve. I have a suspicion that you want to dynamically invoke a
child member function without knowing the child type. That's what
virtual functions are for. You might also take a look at some design
patterns maybe the command or visitor pattern would help. But, as I
say, I don't really get what you're after here. Maybe a little more
clarification is required.

Oct 26 '07 #4

"mathieu" wrote in message
Hi there,

I don't think I'll be able to describe my issue correctly, so
instead I'll just give a pseudo C++ code I am struggling with.
Basically I am looking for a 'pure virtual template' function that I
would be able to declare in the base class (*).

Thanks for suggestions,
-Mathieu
Mathieu,
In The C++ Programming Language, Stroustrup (3rd ed.), in 13.6.2 (page 348),
it says:
"A member template cannot be virtual."
and there follows an explanation.
For more on virtual functions see for example:
http://www.parashift.com/c++-faq-lit...functions.html
Virtual functions are used to make a class runtime (or dynamic) polymorphic.
For a proper runtime polymorphic class you may use the NVI (NonVirtual
Interface) design pattern, see
C++ Coding Standards, Sutter & Alexandrescu.
You may also check out my runtime polymorphic integer class, see N2143 on:
http://open-std.org/jtc1/sc22/wg21/d...mailing2007-01
Of N2143 there will be a third revision in the near future.
Regards, Maarten.
Oct 26 '07 #5
On Oct 26, 2:49 pm, mathieu <mathieu.malate...@gmail.comwrote:
On Oct 26, 2:19 pm, mathieu <mathieu.malate...@gmail.comwrote:
Hi there,
I don't think I'll be able to describe my issue correctly, so
instead I'll just give a pseudo C++ code I am struggling with.
Basically I am looking for a 'pure virtual template' function that I
would be able to declare in the base class (*).

Hum...without much satisfaction here is my temporary solution.
Hopefully you guys will suggest something not involving making the
base class be polymorphic...
Not sure exactly what you are trying to achieve, but this works well
with template classes instead of template functions.
It does use polymorphism, but that is just another way of defining an
interface:

#include <iostream>

template <typename T>
struct Base
{
virtual void foo(T x) = 0;
};

template <typename T>
struct A: Base<T>
{
void foo(T x) { std::cout << "A=" << x << "\n"; }
};

template <typename T>
struct B: Base<T>
{
void foo(T x) { std::cout << "B=" << x << "\n"; }
};

int main(int argc)
{
Base<int*base;
if (argc 1)
base = new A<int>;
else
base = new B<int>;
base->foo(45);
return 0;
}

Oct 26 '07 #6
On 26 oct, 19:58, "Maarten Kronenburg" <M.Kronenb...@inter.nl.net>
wrote:
"mathieu" wrote in message
Hi there,
I don't think I'll be able to describe my issue correctly, so
instead I'll just give a pseudo C++ code I am struggling with.
Basically I am looking for a 'pure virtual template' function that I
would be able to declare in the base class (*).
Thanks for suggestions,
-Mathieu

Mathieu,
In The C++ Programming Language, Stroustrup (3rd ed.), in 13.6.2 (page 348),
it says:
"A member template cannot be virtual."
and there follows an explanation.
For more on virtual functions see for example:http://www.parashift.com/c++-faq-lit...functions.html
Virtual functions are used to make a class runtime (or dynamic) polymorphic.
For a proper runtime polymorphic class you may use the NVI (NonVirtual
Interface) design pattern, see
C++ Coding Standards, Sutter & Alexandrescu.
You may also check out my runtime polymorphic integer class, see N2143 on:http://open-std.org/jtc1/sc22/wg21/d...mailing2007-01
Of N2143 there will be a third revision in the near future.
Regards, Maarten.
Pretty cool ! I did not know about infinite precision integer being
proposed, that's awsome.

Thanks for the NVI info, but I don't think this is the issue here (I
am terrible at describing the issue here).

Thanks
-Mathieu

Oct 27 '07 #7
On 26 oct, 23:40, dvi...@gmail.com wrote:
On Oct 26, 2:49 pm, mathieu <mathieu.malate...@gmail.comwrote:
On Oct 26, 2:19 pm, mathieu <mathieu.malate...@gmail.comwrote:
Hi there,
I don't think I'll be able to describe my issue correctly, so
instead I'll just give a pseudo C++ code I am struggling with.
Basically I am looking for a 'pure virtual template' function that I
would be able to declare in the base class (*).
Hum...without much satisfaction here is my temporary solution.
Hopefully you guys will suggest something not involving making the
base class be polymorphic...

Not sure exactly what you are trying to achieve, but this works well
with template classes instead of template functions.
It does use polymorphism, but that is just another way of defining an
interface:

#include <iostream>

template <typename T>
struct Base
{
virtual void foo(T x) = 0;

};

template <typename T>
struct A: Base<T>
{
void foo(T x) { std::cout << "A=" << x << "\n"; }

};

template <typename T>
struct B: Base<T>
{
void foo(T x) { std::cout << "B=" << x << "\n"; }

};

int main(int argc)
{
Base<int*base;
if (argc 1)
base = new A<int>;
else
base = new B<int>;
base->foo(45);
return 0;

}

I can't move the template at the class level unfortunately.

Explanation:
My objects can be serialized either in big endian or little endian. So
the design is :

struct Object
{
...
void Read<Swapper>(ostream &os) { ... }
void Write<Swapper>(ostream &os) { ... }
}

Where swapper is either a no-op or actually do a byte-swap. So
template at the class level would not make much sense.

Thanks anyway,
-Mathieu

Oct 27 '07 #8
On Oct 27, 8:47 pm, mathieu <mathieu.malate...@gmail.comwrote:
On 26 oct, 23:40, dvi...@gmail.com wrote:
My objects can be serialized either in big endian or little endian.
Depending on what?
So
the design is :

struct Object
{
...
void Read<Swapper>(ostream &os) { ... }
void Write<Swapper>(ostream &os) { ... }
}
Where swapper is either a no-op or actually do a byte-swap. So
template at the class level would not make much sense.
I'm not sure I understand this at all. Why would you want to
swap anything. You have two output formats. If the choice is
runtime, you have to include the implementation of both in your
code. If the choice is compile time, you include one or the
other at link time. In both cases, it's pretty transparent to
the user; in the first case, you use the strategy pattern, and
the user has to specify the strategy once up front, and in the
second, it's totally transparent, since the decision is made
when you link.

And of course, you never "swap" anything. You simply write the
data in the target format.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Oct 28 '07 #9
On 28 oct, 10:56, James Kanze <james.ka...@gmail.comwrote:
On Oct 27, 8:47 pm, mathieu <mathieu.malate...@gmail.comwrote:
On 26 oct, 23:40, dvi...@gmail.com wrote:
My objects can be serialized either in big endian or little endian.

Depending on what?
So
the design is :
struct Object
{
...
void Read<Swapper>(ostream &os) { ... }
void Write<Swapper>(ostream &os) { ... }
}
Where swapper is either a no-op or actually do a byte-swap. So
template at the class level would not make much sense.

I'm not sure I understand this at all. Why would you want to
swap anything. You have two output formats. If the choice is
runtime, you have to include the implementation of both in your
code. If the choice is compile time, you include one or the
other at link time. In both cases, it's pretty transparent to
the user; in the first case, you use the strategy pattern, and
the user has to specify the strategy once up front, and in the
second, it's totally transparent, since the decision is made
when you link.

And of course, you never "swap" anything. You simply write the
data in the target format.
Hi James,

That is correct I have 'two' implementations (only different by one
operation: byte swapping). Thus my Object O can be written in little
or big endian. Therefore the 'endian' template parameter cannot be at
the class level (as suggested by previous poster).
Since code is cross platform, and choice is done at run-time (user
cannot know ahead of time which format he is reading) I simply pass a
'swapper' template parameter that will decide depending on file format
and architecture how to read words.

Thanks for your interest,
-Mathieu

Oct 29 '07 #10
On Oct 29, 2:54 pm, mathieu <mathieu.malate...@gmail.comwrote:
On 28 oct, 10:56, James Kanze <james.ka...@gmail.comwrote:
On Oct 27, 8:47 pm, mathieu <mathieu.malate...@gmail.comwrote:
On 26 oct, 23:40, dvi...@gmail.com wrote:
My objects can be serialized either in big endian or little endian.
Depending on what?
So
the design is :
struct Object
{
...
void Read<Swapper>(ostream &os) { ... }
void Write<Swapper>(ostream &os) { ... }
}
Where swapper is either a no-op or actually do a byte-swap. So
template at the class level would not make much sense.
I'm not sure I understand this at all. Why would you want to
swap anything. You have two output formats. If the choice is
runtime, you have to include the implementation of both in your
code. If the choice is compile time, you include one or the
other at link time. In both cases, it's pretty transparent to
the user; in the first case, you use the strategy pattern, and
the user has to specify the strategy once up front, and in the
second, it's totally transparent, since the decision is made
when you link.
And of course, you never "swap" anything. You simply write the
data in the target format.
That is correct I have 'two' implementations (only different by one
operation: byte swapping).
But why would you ever "swap" bytes? You write big endian, or
you write little endian. Or you write some other format---in
all cases, you have a *value* (int, whatever) which must be
output in a specified format. You convert the value to the
format, and that's it.
Thus my Object O can be written in little or big endian.
Therefore the 'endian' template parameter cannot be at the
class level (as suggested by previous poster).
Since code is cross platform, and choice is done at run-time (user
cannot know ahead of time which format he is reading) I simply pass a
'swapper' template parameter that will decide depending on file format
and architecture how to read words.
If the choice is run-time, you can't use templates. I'd go with
the strategy pattern. Something like:

class Writer
{
public:
virtual ~Writer() {}
virtual void write( std::ostream& dest, int value ) const =
0 ;
// and so on for each type.
}

class BEWriter : public Writer
{
public:
virtual void write( std::ostream& dest, int value ) const
{
uint32_t tmp = value ;
dest.put( (tmp >24) & 0xFF ) ;
dest.put( (tmp >16) & 0xFF ) ;
dest.put( (tmp > 8) & 0xFF ) ;
dest.put( (tmp ) & 0xFF ) ;
}
// and so on for each type...
} ;

class LEWriter : public Writer
{
public:
virtual void write( std::ostream& dest, int value ) const
{
uint32_t tmp = value ;
dest.put( (tmp ) & 0xFF ) ;
dest.put( (tmp > 8) & 0xFF ) ;
dest.put( (tmp >16) & 0xFF ) ;
dest.put( (tmp >24) & 0xFF ) ;
}
// and so on for each type...
} ;

You then initialize a Writer* in your output class to whichever
one is relevant, and output through it. You can even change on
the fly---first 10 integers in big endian, next 10 in little,
etc.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Oct 29 '07 #11
On Oct 29, 4:21 pm, James Kanze <james.ka...@gmail.comwrote:
On Oct 29, 2:54 pm, mathieu <mathieu.malate...@gmail.comwrote:
On 28 oct, 10:56, James Kanze <james.ka...@gmail.comwrote:
On Oct 27, 8:47 pm, mathieu <mathieu.malate...@gmail.comwrote:
On 26 oct, 23:40, dvi...@gmail.com wrote:
My objects can be serialized either in big endian or little endian.
Depending on what?
So
the design is :
struct Object
{
...
void Read<Swapper>(ostream &os) { ... }
void Write<Swapper>(ostream &os) { ... }
}
Where swapper is either a no-op or actually do a byte-swap. So
template at the class level would not make much sense.
I'm not sure I understand this at all. Why would you want to
swap anything. You have two output formats. If the choice is
runtime, you have to include the implementation of both in your
code. If the choice is compile time, you include one or the
other at link time. In both cases, it's pretty transparent to
the user; in the first case, you use the strategy pattern, and
the user has to specify the strategy once up front, and in the
second, it's totally transparent, since the decision is made
when you link.
And of course, you never "swap" anything. You simply write the
data in the target format.
That is correct I have 'two' implementations (only different by one
operation: byte swapping).

But why would you ever "swap" bytes? You write big endian, or
you write little endian. Or you write some other format---in
all cases, you have a *value* (int, whatever) which must be
output in a specified format. You convert the value to the
format, and that's it.
Thus my Object O can be written in little or big endian.
Therefore the 'endian' template parameter cannot be at the
class level (as suggested by previous poster).
Since code is cross platform, and choice is done at run-time (user
cannot know ahead of time which format he is reading) I simply pass a
'swapper' template parameter that will decide depending on file format
and architecture how to read words.

If the choice is run-time, you can't use templates. I'd go with
the strategy pattern. Something like:

class Writer
{
public:
virtual ~Writer() {}
virtual void write( std::ostream& dest, int value ) const =
0 ;
// and so on for each type.
}

class BEWriter : public Writer
{
public:
virtual void write( std::ostream& dest, int value ) const
{
uint32_t tmp = value ;
dest.put( (tmp >24) & 0xFF ) ;
dest.put( (tmp >16) & 0xFF ) ;
dest.put( (tmp > 8) & 0xFF ) ;
dest.put( (tmp ) & 0xFF ) ;
}
// and so on for each type...
} ;

class LEWriter : public Writer
{
public:
virtual void write( std::ostream& dest, int value ) const
{
uint32_t tmp = value ;
dest.put( (tmp ) & 0xFF ) ;
dest.put( (tmp > 8) & 0xFF ) ;
dest.put( (tmp >16) & 0xFF ) ;
dest.put( (tmp >24) & 0xFF ) ;
}
// and so on for each type...
} ;

You then initialize a Writer* in your output class to whichever
one is relevant, and output through it. You can even change on
the fly---first 10 integers in big endian, next 10 in little,
etc.
Hi James,

Thanks for taking the time to detail your solution. However I still
think that template apply in this case. I am basically doing the same,
except that I have a Swapper class that is doing the:

void DoTheIntSwap() {
(tmp ) & 0xFF ;
(tmp > 8) & 0xFF ;
(tmp >16) & 0xFF ;
(tmp >24) & 0xFF ;
}

Therefore that I can reuse code in between Reader & Writer:

http://gdcm.svn.sourceforge.net/view....h?view=markup

Finally you use -I think- the visitor pattern. I tried it and it
gives something real ugly:

http://gdcm.svn.sourceforge.net/view...97&view=markup

Basically I need to make IOSerialize of friend of every single
structure I am using in my code. Pretty ugly, heh ?
So instead each structure has access to its private member and can
easily write them. Eg.

template <typename TSwap>
IStream &Read(IStream &is)
{
is.read(ElementTag.bytes, 4);
TSwap::SwapArray(ElementTag.tags, 2); // Will expand to nothing
when writing file format match OS (e.g Big Endian file on big endian
machine)
return is;
}

template <typename TSwap>
const OStream &Write(OStream &os) const
{
uint16_t copy[2]; // local copy since function is
const
copy[0]= ElementTag.tags[0];
copy[1]= ElementTag.tags[1];
TSwap::SwapArray(copy, 2);
return os.write((char*)(&copy), 4);
}

Ref:
http://gdcm.svn.sourceforge.net/view...tion/gdcmTag.h

Thanks again for your time, this is very much appreciated as it took
me multiple iterations and I am still not entirely satisfied: template
functions in non-template classes are ugly to use :(

-Mathieu

Oct 29 '07 #12

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

12
13428
by: cppaddict | last post by:
Hi, I know that it is illegal in C++ to have a static pure virtual method, but it seems something like this would be useful when the following 2 conditions hold: 1. You know that every one...
6
6188
by: Dilip | last post by:
Hi All I have a pure virtual function in my base class that my derived instances override. What are the likely causes for VC++ 7.1 to complain of unresolved external symbol on that pure virtual...
3
4580
by: Dmitry Prokoptsev | last post by:
Hello, I need to write a class for exceptions which can be thrown, caught, stored and thrown once again. I have written the following code: --- begin --- #include <string> class Exception...
3
3689
by: nw | last post by:
Hi, I have three classes, a template pure virtual base class, a template derived class and a third which I would like to use to store copies of the derived class. The code looks like this: ...
3
3300
by: YellowMaple | last post by:
Is it possible to have pure virtual functions defined in a template class? I'm trying to do something like this: template <typename T> class Singleton { public: static T& getInstance(void) {...
2
4219
by: vilarneto | last post by:
Hello everyone, I'm facing a particular situation about template class derivation. The subject is old -- deriving a non-template class from a template base class -- but my problem is that the...
6
4015
by: Miguel Guedes | last post by:
Hello, I recently read an interview with Bjarne Stroustrup in which he says that pure abstract classes should *not* contain any data. However, I have found that at times situations are when it...
13
7239
by: Mike -- Email Ignored | last post by:
Is a pure virtual function in allowed in a template base class? In any case, I have one working. Am I skating on thin ice? Thanks, Mike.
7
7321
by: Tonni Tielens | last post by:
I'm trying to create a pure virtual class describing an interface. Normally, when I do this I make the destructor pure virtual so that, even if there are no members in the class, it cannot be...
0
7254
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
7373
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
7519
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
5677
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
1
5079
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
4743
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
1585
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...
1
796
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
452
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.