Sign in to follow this  
slicer4ever

specialize part of function by template type?

Recommended Posts

i'm having a problem on figuring out how to basically do the following:

[code]
template<class T>
void function(int len, ...){
va_list lst;
va_start(lst, len);
for(int i=0;i<len;i++){
#ifdef T==float
va_arg(lst, double);
#else
va_arg(lst, T);
#endif
}
va_end(lst);
return;
}
[/code]
i have come up with a solution like so:
[code]
template<class T>
void function(int len, ...){
va_list lst;
va_start(lst, len);
unsigned char TFlag=typeid(T)==typeid(float)
for(int i=0;i<len;i++){
if(TFlag) (float)va_arg(lst, double);
else va_arg(lst, T);
}
va_end(lst);
return;
}
[/code]
however i'd prefer a solution similar to the first one, so that no extra logic has to be applied(and the second one throws warnings if using type of other than a double).

p.s. remember, just a sample of what i'm trying to do, so please don't hold up on the fact that this code doesn't accomplish anything.

Share this post


Link to post
Share on other sites
[code]
#include <iostream>
#include <cstdarg>

using namespace std;

namespace function_impl {
template<class type>
struct traits {
typedef type varg_type;
};

template<>
struct traits<float> {
typedef double varg_type;
};
}

template<class type>
void function( int len, ... ) {
va_list lst;
va_start( lst, len );
for ( int i = 0; i < len; ++i )
cout << static_cast<type>(va_arg(lst, typename function_impl::traits<type>::varg_type)) << ' ';
va_end(lst);
}

int main() {
function<float>( 4, 1.12f, 2.23f, 3.34f, 4.45f );
function<double>( 4, 1.12, 2.23, 3.34, 4.45 );
function<int>( 3, 1, 2, 3 );
function<char>( 2, 'a', 'b' );
function<short>( 2, 'a', 'b' );
}

[/code]

Gotta wash my mouth out with soap now, brb.

Share this post


Link to post
Share on other sites
If you really still need to use C-style variadic functions, this is the cleanest way to do what I think you want to do.

[code]#include <iostream>
#include <stdarg.h>


// The actual implementation takes a variadic argument list descriptor.
template<class T>
void function(int len, va_list args) {
for (int i = 0; i < len; ++i)
std::cout << va_arg(args, T) << ' ';
std::cout << '\n';
}


// The general signature is actually variadic, and forwards to the guts.
template<class T>
void function(int len, ...) {
va_list args;
va_start(args, len);
function<T>(len, args);
va_end(args);
}


// The float signature is also variadic, and forwards with a promotion to double.
template<>
void function<float>(int len, ...) {
va_list args;
va_start(args, len);
function<double>(len, args);
va_end(args);
}


// Tests.
int main(int argc, char** argv) {

function<int>(3, 1, 2, 3);
function<float>(3, 1.0, 2.0, 3.0);

}
[/code]

However, this is all essentially a crufty workaround for the issue of type promotion when it comes to how well C-style variadic arguments interact with templates—which is to say not very well. If you can use a C++0x compiler (and unless your circumstances are strange indeed, you likely can) here's a much safer and cleaner solution using variadic templates:

[code]#include <iostream>


// When only one argument is given, handle it.
template<class T>
void function2(T only) {
std::cout << only;
}


// When multiple arguments are given, handle them.
// Oh, and automatically assert that they are all of the same type.
// Oh, and no need to worry about type promotion.
// Oh, and all of this recursive template expansion happens at compile-time.
template<class T, class... Rest>
void function2(T first, Rest... rest) {
std::cout << first << ' ';
function2<T>(rest...);
std::cout << '\n';
}

// No need to mess with argument counts, either.
// Not to mention specifying the type is optional as well.
int main(int argc, char** argv) {

function2("foo", "bar", "baz");
function2(4, 5, 6);
function2<float>(4.1, 5.2, 6.3);

}
[/code]

So download the latest GCC and have fun. :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this