# specialize part of function by template type?

This topic is 2465 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

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

 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; } 
i have come up with a solution like so:
 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; } 
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 on other sites
 #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' ); } 

Gotta wash my mouth out with soap now, brb.

##### 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.

#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); } 

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:

#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); } 

So download the latest GCC and have fun.