template #if preprocessor

K

kRyszard

how to make the following code work:

template<class TYPE>
void f2(char *buffer, TYPE *outer) {
// do something ...
// ...
#if (TYPE == int)
*outer = atoi(buffer);
#endif
#if (TYPE == double)
*outer = atof(buffer);
#endif
#if (TYPE == char)
strcpy(outer, buffer);
#endif
// release memory here
// ...
return;
}

it is not working but maybe you know how to modify it to make it
work...
K
 
B

Barry

kRyszard said:
how to make the following code work:

template<class TYPE>
void f2(char *buffer, TYPE *outer) {
// do something ...
// ...
#if (TYPE == int)
*outer = atoi(buffer);
#endif
#if (TYPE == double)
*outer = atof(buffer);
#endif
#if (TYPE == char)
strcpy(outer, buffer);
#endif
// release memory here
// ...
return;
}

it is not working but maybe you know how to modify it to make it
work...
K

macro and preprocessor are done during preprocessing time,
template initiation is done compile-time, which is after
preprocessing-time, you can't mix them up
 
A

Alf P. Steinbach

* kRyszard:
how to make the following code work:

template<class TYPE>
void f2(char *buffer, TYPE *outer) {
// do something ...
// ...
#if (TYPE == int)
*outer = atoi(buffer);
#endif
#if (TYPE == double)
*outer = atof(buffer);
#endif
#if (TYPE == char)
strcpy(outer, buffer);
#endif
// release memory here
// ...
return;
}

it is not working but maybe you know how to modify it to make it
work...

As "Barry" remarked else-thread, the preprocessor knows nothing about
types and arguments.

In principle you could just use an ordinary overloaded function.

But I suggest using boost::lexical_cast, because that works.
 
B

Barry

kRyszard said:
how to make the following code work:

template<class TYPE>
void f2(char *buffer, TYPE *outer) {
// do something ...
// ...
#if (TYPE == int)
*outer = atoi(buffer);
#endif
#if (TYPE == double)
*outer = atof(buffer);
#endif
#if (TYPE == char)
strcpy(outer, buffer);
#endif
// release memory here
// ...
return;
}

it is not working but maybe you know how to modify it to make it
work...

As Alf mentioned, boost::lexical_cast maybe work well with only the
integral types in your case; from the OP, when the type is char, the
function just wants to do a string copy.

So my suggestion is don't borrow template if it's only because it's fancy.

you can do the integral types with template using lexical_cast, and
write an additional overloaded function to handle type char


#include <boost/lexical_cast.hpp>
#include <iostream>

using namespace boost;
using namespace std;

template <typename T>
T f2(char const* buffer) {
return lexical_cast<T>(buffer);
}

void f2(char const* buffer, char* out) {
strcpy(out, buffer);
}

int main()
{
cout << f2<int>("1000") << endl;
cout << f2<double>("1.0") << endl;

char out[100];
f2("hello", out);
cout << out << endl;
}
 
J

joe

how to make the following code work:

template<class TYPE>
void f2(char *buffer, TYPE *outer) {
// do something ...
// ...
#if (TYPE == int)
*outer = atoi(buffer);
#endif
#if (TYPE == double)
*outer = atof(buffer);
#endif
#if (TYPE == char)
strcpy(outer, buffer);
#endif
// release memory here
// ...
return;

}

First thing, as was mentioned else where, the #if statements are
preprocessor statements and are applied well before the template
instantiation mechanism comes into play. Second, for what you are
doing, you can just use function overloads to implement your
conversions. That is,

void f2(char * buffer, char * out)
{

}

If you are going to mess with templates, I would suggest "C++
Templates" by Vandevoorde and Josuttis, however I can give you a
couple of pointers to get you started.

First, consider an existing solution such as boost::lexical_cast
(www.boost.org). The only problem with it is that it uses streams as
it's underpinnings and can therefore be slow compared to atoi() etc.
Most often though, this kind of conversion isn't done often enough to
warrant more effort than that.

If you feel that you are in the category where performance matters or
if you are just doing this as an exercise to learn templates, then I
can offer the following advice.

1) All of the # prefixed statements are C++ preprocessor statements
and don't work the way you are trying above.

2) The way you would set up your template specializations would look
like:

template <typename TYPE>
void f2(char * buffer, TYPE *outer)
{
// Do something generic like whine about this conversion not being
taken into account or possibly
// use #error
}

// Now specialize for the cases we know how to handle

template <>
void f2<int>(char * buffer, int * outer)
{
// convert to int
*outer = atoi(buffer);
}

template <>
void f2<double>(char * buffer, double * outer)
{
// convert to double
*outer = atof(buffer);
}

// the rest follow a similar pattern

Now, I didn't change the interface from what you posted, but
somewhere, you will want to verify that someone didn't just ask to
convert "Hello World" into a double or whatever, but since I don't
know your inputs I won't say much else about that.
 
J

joe

Ahhh, I've been Googled. Didn't mean to submit the last message.

Anyway, I was going to recommend just a series of function overloads
instead of the templates.

void f2(char * buffer, char * out)
{
// handle char *


}
void f2(char * buffer, int * out)
{
*out = atoi(buffer);


}

And so forth. No need for templates for this usage. However, I did
give in the previous, not quite edited in the way I would wish
message, a way to do it with templates. :) I'm quitting now before I
do some other weird edit and send thing.

joe
 
J

James Kanze

how to make the following code work:
template<class TYPE>
void f2(char *buffer, TYPE *outer) {
// do something ...
// ...
#if (TYPE == int)
*outer = atoi(buffer);
#endif
#if (TYPE == double)
*outer = atof(buffer);
#endif
#if (TYPE == char)
strcpy(outer, buffer);
#endif
// release memory here
// ...

None of my business, of course, but what memory are you
releasing?
return;
}
it is not working but maybe you know how to modify it to make it
work...

In this precise case, of course, the obvious solution is:

template< typename T >
void
f2( char const* buffer, T* dest )
{
std::istrstream s( buffer, strlen( buffer ) ) ;
s >> *dest ;
// Error checking here...
}

If this is just an example of a more general problem, of
course...

template< typename T >
struct Cvt
{
static T convert( char const* buffer ) ;
} ;

template< typename T >
void
f2( char const* buffer, T* dest )
{
// ...
*dest = Cvt< T >::convert( buffer ) ;
// ...
}

template<>
struct Cvt< int >
{
static int convert( char const* buffer )
{
return atoi( buffer ) ;
}
} ;

template<>
struct Cvt< double >
{
static int convert( char const* buffer )
{
return atof( buffer ) ;
}
} ;

// ...
 

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

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top