473,569 Members | 2,772 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Interesting question about Templates & RTTI

I have tried to compile the following code on Win & Unix. Doesn't work
on either.
<----- CODE ----->
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <vector>
#include <typeinfo>
using namespace std;

template <class T>
class MyArray
{
private:
vector<T_data;
public:
void foo(void* mem_buf, int buf_size)
{
if(typeid(T) == typeid(string))
{
char buf[1000]={0};
strncpy(buf, (char*)mem_buf, buf_size);
_data[0] = string(buf);
return;
}

if(typeid(T) == typeid(int))
{
int tmp;
mempcy((void*)& tmp, mem_buf, sizeof(T));
_data[0] = tmp;
return;
}
}
};

int main()
{
MyArray<inta;
int b =5;
a.foo((void*)&b , sizeof(b));
}

<---- END CODE --->

Win VC8 gives 2 errors:
1) For the line: _data[0] = string(buf); :
error C2440: '=' : cannot convert from
'std::basic_str ing<_Elem,_Trai ts,_Ax>' to 'int'
with
[
_Elem=char,
_Traits=std::ch ar_traits<char> ,
_Ax=std::alloca tor<char>
]
No user-defined-conversion operator available that can perform
this conversion, or the operator cannot be called

2) For the line: mempcy((void*)& tmp, mem_buf, sizeof(T));:
error C3861: 'mempcy': identifier not found
Unix g++ 4.1.0 20060304 (Red Hat 4.1.0-3) on i386-redhat-linux gives:
test3.cpp: In member function void MyArray<T>::foo (void*, int):
test3.cpp:28: error: there are no arguments to ×’mempcy that depend on
a template parameter, so a declaration of mempcy must be available
test3.cpp:28: error: (if you use -fpermissive, G++ will accept your
code, but allowing the use of an undeclared name is deprecated)

The problem seems to be that the VC8 compiler is trying to compile the
code with the given T=int, so on the line that says _data[0] =
string(buf);
it is trying to insert a string into an <intvector. I could dig
that, but it seems annoying that there is no way around that. What I
want to achieve is a template that I can use, where I can parse data
that I get according to its type in runtime.
If there is no other option, I will probably use a base class and
derive from it instead of templates. They just seemed a cleaner
solution. If you have any thoughts- I would love to hear them.
Now, g++ doesn't seem to be bothered by this problem- which is kinda
weird.

The other thing is the problem with memcpy. Anyone can shed a light on
that?
Thanks
Sagi

Nov 30 '06 #1
8 3095
* sa********@gmai l.com:
I have tried to compile the following code on Win & Unix. Doesn't work
on either.
<----- CODE ----->
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <vector>
#include <typeinfo>
using namespace std;

template <class T>
class MyArray
{
private:
vector<T_data;
public:
void foo(void* mem_buf, int buf_size)
{
if(typeid(T) == typeid(string))
{
char buf[1000]={0};
strncpy(buf, (char*)mem_buf, buf_size);
_data[0] = string(buf);
return;
}

if(typeid(T) == typeid(int))
{
int tmp;
mempcy((void*)& tmp, mem_buf, sizeof(T));
_data[0] = tmp;
return;
}
}
};

int main()
{
MyArray<inta;
int b =5;
a.foo((void*)&b , sizeof(b));
}
The compiler complains because _data[0] is of type 'int'. That in turn
is because you've treated it as being of two different types in the same
piece of code. There are techniques for doing that but those are
compile-time techniques, causing the compiler to not even look at the
code that's not used; for a run-time decision you can't do that since
both codes need to be present to choose one or the other.

How about

template<typena me T>
class MyArray
{
private:
std::vector<Tmy Data;
public:
void setFirstElement ( T const& value )
{
myData.at( 0 ) = value;
}

// Whatever, other things.
};

which seems to do all you're attempting with 'foo', only far easier, far
more safe and probably more efficient too (not to mention correct). ;-)

The other thing is the problem with memcpy. Anyone can shed a light on
that?
Be glad that the compiler reported some error.

What book are you using that recommends such evilness as displayed above?

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Nov 30 '06 #2

sa********@gmai l.com wrote:
I have tried to compile the following code on Win & Unix. Doesn't work
on either.
<----- CODE ----->
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <string>
#include <vector>
#include <typeinfo>
using namespace std;

template <class T>
class MyArray
{
private:
vector<T_data;
underscores at the start of a var name are reserved.
The above will fail if T is itself a template (hint: std::string) since
<<...>is parsed as an input stream operator.
MyArray should have a default ctor or a parametized ctor so as to
initialize the member vector.
public:
void foo(void* mem_buf, int buf_size)
{
if(typeid(T) == typeid(string))
Why detect the type? Read below...
Please stop thinking of std::string as a bunch of characters, its a
type, just like int is a type.
In fact its more than just a type, its a dynamic type.
{
char buf[1000]={0};
strncpy(buf, (char*)mem_buf, buf_size);
_data[0] = string(buf);
return;
}

if(typeid(T) == typeid(int))
{
int tmp;
mempcy((void*)& tmp, mem_buf, sizeof(T));
_data[0] = tmp;
return;
}
}
};

int main()
{
MyArray<inta;
int b =5;
a.foo((void*)&b , sizeof(b));
}

<---- END CODE --->
Let me welcome you to the 21st century:

#include <iostream>
#include <string>
#include <vector>

class Dummy // for observing output
{
public:
Dummy() { std::cout << "Dummy()\n" ; }
Dummy(const Dummy& copy) // copy ctor
{
std::cout << "copy Dummy\n";
}
~Dummy() { std::cout << "~Dummy()\n "; }
};

template < class T >
class MyVector
{
std::vector< T vt;
public:
// def ctor
MyVector() : vt() { }
// parametized ctor
MyVector(const size_t& sz, const T& t = T())
: vt(sz, t) { }
};

int main()
{
MyVector< int vn(1000000, 99);
MyVector< std::string vs(10, "string");
MyVector< Dummy vdum(5);
}

/*
Dummy()
copy Dummy // thats so cool
copy Dummy
copy Dummy
copy Dummy
copy Dummy
~Dummy()
~Dummy()
~Dummy()
~Dummy()
~Dummy()
~Dummy()
*/

It doesn't get any simpler. By the way: std::string already has a
default ctor so:
MyVector< std::string vs(10);
will do. Ahem - those 10 strings are empty but all dynamic.
The MyVector class would benefit from a copy ctor and assignment
operator, both easy to implement. So now you can take both strncpy and
mempcy and throw them in the garbage.

MyVector< int vn(1000000, 99);
Just in case you missed it, thats 1 million instant integers all
initialized to 99 on *one* line.

Nov 30 '06 #3
Thanks for the reply!
Your suggestion is much more elegant, but it will not solve my problem.
Let me explain.

The code I posted here is just a simplification of what I doing: it's
all part of a system for data messaging between different
architectures.
I am reading a memory buffer from a remote source, and that buffer has
a non constant format.
Along with it, I also get an object holding information which tells me
what the memory buffer represents.
For example, it will tell me that the buffer holds 5 ints, then a
double, then a string sized 45 bytes etc.
I have to "parse" the buffer in real time to get the actual data.

I could make a class for every possible data type, but templates seemed
more convenient, since all those classes would have the exact same
functionality.
So getting a memory buffer is a must for me. I cannot modify the
function to get a T type.

As far as the memcpy- I know it's evil, but I don't know any other fast
way to extract data from a memory chunk into a variable. How would you
extract the value of an int from a (void*) memory chunk?

Hope I made myself clear.
I will be glad if you have any thoughts...
Thanks, Sagi

Nov 30 '06 #4
sa********@gmai l.com wrote:
As far as the memcpy- I know it's evil, but I don't know any other fast
way to extract data from a memory chunk into a variable. How would you
extract the value of an int from a (void*) memory chunk?
How about:

int main()
{
int i = 42;
void *p = &i;
int j = *static_cast<in t*>(p);
}
Nov 30 '06 #5
Thanks Nate!
That is a much safer way.

Do you have any insight about the template problem, or do you figure
that separate classes for different data types would be the best
solution?

Nov 30 '06 #6
sa********@gmai l.com a écrit :
Thanks Nate!
That is a much safer way.

Do you have any insight about the template problem, or do you figure
that separate classes for different data types would be the best
solution?
It's not safer than a memcpy version, although at least it's more
elegant.

For your template problem, I think you have to make a design decision
here: if you need to know the real type of T when you process the data,
then something is wrong - as this is a clear breach of the Open/Closed
principle (see wikipedia or c2.com for more info). Templates should
allow you to create code that is generic. Reintroducing type name into
this don't make much sense IMHO.

I guess that the data you are processing comes from some sort of file,
maybe a socket (that would explain why you need to use a raw buffer +
its size ; if it's not the case, please give us more information about
what you want to achieve, as there may be a better solution). A
classical solution for this problem is to use a helper template
function that can be specialized. For example:

#include <algorithm// for std::copy

template <class T>
void copy_from_raw(T & dest, void *buf, std::size_t size)
{
// unspecialized, raw copy:
char *temp = reinterpret_cas t<char*>(&buf) ;
int min_size = std::min(sizeof (T), size)
std::copy(temp, temp+min_size, reinterpret_cas t<char*>(&temp) );
}

template <>
void copy_from_raw<i nt>(int& dest, void *buf, std::size_t size)
{
dest = *(reinterpret_c ast<int*>(buf)) ;
}

template <>
void copy_from_raw<s td::string>(str ing& dest, void *buf, std::size_t
size)
{
dest.resize(siz e);
char *temp = reinterpret_cas t<char*>(&buf) ;
std::copy(temp, temp + size, dest.begin());
}

(I used reinterpret_cas t instead of static_cast because I want to make
clear that the void* source is really unrelated to the destination
type).

In the code, you use:

template <class T>
class my_array
{
std::vector<Tv;
public:
void foo(void *buf, std::size_t size)
{
T dest;
// if T is int, it will call copy_from_raw<i nt>(); if T is a string
it will call
// copy_from_raw<s td::string>(); otherwise it will call the generic
version
// of copy_from_raw<T >()
copy_from_raw(d est, buf, size);
v.push_back(des t);
}
};

The reason why you use an external function is that you can easily
specialize it, which keep your template code generic. There are some
example of this technique in the standard library itself.

HTH,

-- Emmanuel Deloget, Artware

Nov 30 '06 #7
Dear Emmanuel Deloget
Thank you for your reply. Your suggestion did solve my problem!
The external functions do enable the template code to remain general,
and this is exactly what I needed. Too bad the C++ books I have do not
mention such a design. They do mention typeid as a solution which is a
lot uglier.

As par your questions:
the data is coming from sockets and pipes, some of it directly from
hardware drivers that I do not have control over; and I would hate to
make a wrapper for them to format the data for me.
The module that I am building interfaces with various other processes
and collects data from them. The data format changes in runtime, but
the header of each message that I get specifies the format.

You said that cast is just as safe as memcpy. Is that the case? memcpy
can cause you to overrun a buffer.
Will cast do the same?
I can imagine that interpret_cast would, if you are forcing a cast to
something that is bigger than the real data.

Thanks again!

Dec 1 '06 #8

sa********@gmai l.com a écrit :
Dear Emmanuel Deloget
Thank you for your reply. Your suggestion did solve my problem!
The external functions do enable the template code to remain general,
and this is exactly what I needed. Too bad the C++ books I have do not
mention such a design. They do mention typeid as a solution which is a
lot uglier.
Most books that have been written in the 2000-2003 era are very
object-oriented. While the procedural+OO mix is not new, it has (IMHO)
not been seen as a very valid programming paradigm until recently
(despite the STL architecture). This is changing rapidly, as this mix
enables you to express not only things (objects) but also actions
(functions). However, this is quite out of subject here :)
<snip>

You said that cast is just as safe as memcpy. Is that the case? memcpy
can cause you to overrun a buffer.
Will cast do the same?
I can imagine that interpret_cast would, if you are forcing a cast to
something that is bigger than the real data.
Whenever you use a cast or use memcpy (which will either requires an
explicit cast or do an implicit cast), you quit the wonderful realm of
type safety, and the ugly witch of the dark forest of the bugs will now
be able to catch you and boil you. As a consequence, it's far better to
avoid any solution that use void* or pointer type cast when possible.
Now, you're also true that memcpy also allow you to override memory
(but then a pointer cast allow you to do very nasty things as well).
Thanks again!
You're welcome :)

-- Emmanuel Deloget, Artware

Dec 4 '06 #9

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

Similar topics

14
1803
by: Gabriel Zachmann | last post by:
This post is not strictly Python-specific, still I would like to learn other university teachers' opinion. Currently, I'm teaching "introduction to OO programming" at the undergrad level. My syllabus this semester consists of a bit of Python (as an example of a scripting language) and C++ (as an example of a compiled language). With C++, I...
9
7216
by: Philip Lawatsch | last post by:
Hi, I have some questions about whats written in http://www.parashift.com/c++-faq-lite/dtors.html#faq-11.14 (Describing some memory pool) #1 From what i understand this will also work for new x and delete x, or did i misunderstand something ? and,
5
4476
by: SainTiss | last post by:
Hi, Is there an extra overhead in using virtual functions and templates? Or is is just the same overhead as with regular classes? Either way, if you'd want to avoid it, will you always end up with code duplication? For example: let's say you've got two template specializations, which differ only slightly... So you put the common...
3
1705
by: Fran Cotton | last post by:
Hi, I'd greatly appreciate it if someone could cast light on my problem - I can't seem to find any reference to it anywhere. Consider the following XML: <paragraph> I am <emphasize>emphasized</emphasize> text inside a paragraph </paragraph> How do I go about transforming this into HTML like the following: <P>I am <EM>emphasized</EM>...
6
1937
by: Kleidemos | last post by:
If I implement a simple RTTI system, more simple than C++ RTTI system for my program and this system is plus or minus: #define DEF_RTTI_BASE(name) virtual inline const char *Name(){ return #name; } #define DEF_RTTI(name) inline const char *Name(){ return #name; } And(for example) class CProva
9
4615
by: Agoston Bejo | last post by:
Hello there, I would like to know what overheads there are to think of when using RTTI. I understand that enabling RTTI increases the sizes of the classes, but not the objects themselves. This doesn't sound too bad. What I'm worried about is whether there is a general performance overhead caused by enabling RTTI, such as enabling exceptions...
2
2042
by: norton | last post by:
Hi, I am learning Regular Expression and currently i am trying to capture information from web page. I wrote the following code to capture the ID as well as the Title Dim regex = New Regex( _ "viewtopic.php\?t=(?<ID>\d+)""\sclass=""topictitle"">(?<Title>.*)\</a>", _ RegexOptions.IgnoreCase _
23
2570
by: Ben Voigt | last post by:
I have a POD type with a private destructor. There are a whole hierarchy of derived POD types, all meant to be freed using a public member function Destroy in the base class. I get warning C4624. I read the description, decided that it's exactly what I want, and ignored the warning. Now I'm trying to inherit using a template. Instead of...
2
2238
by: Chameleon | last post by:
I know than dynamic_cast check string name of derived to base class and if one of them match, return the pointer of that object or else zero. I suppose, I dynamic_cast instead of strings, checks integers, then this procedure will be more fast, so I create something like this: --------------------------------------------- class A {...
0
7694
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, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main...
0
8118
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
0
7964
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 protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the...
1
5504
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 presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes...
0
5217
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 then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert...
0
3636
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2107
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 we have to send another system
1
1208
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
936
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 can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating...

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.