Reputation: 3223
Let's assume we have a template function "foo":
template<class T>
void foo(T arg)
{ ... }
I can make specialization for some particular type, e.g.
template<>
void foo(int arg)
{ ... }
If I wanted to use the same specialization for all builtin numeric types (int, float, double etc.) I would write those lines many times. I know that body can be thrown out to another function and just call of this is to be made in every specialization's body, however it would be nicer if i could avoid writting this "void foo(..." for every type. Is there any possibility to tell the compiler that I want to use this specialization for all this types?
Upvotes: 15
Views: 4429
Reputation: 1578
Here's a refinement of Johannes solution, but easier to read. Just do the type check inside the function:
template<typename T>
void foo(T arg)
{
if (numeric_limits<T>::is_specialized) // not a runtime check - compile time constant
{
}
else
{
}
}
Using type traits (which itself is template specialization) allows replacing a bunch of template specializations with a single, easy to read function template
Upvotes: 0
Reputation: 35188
You could write a small script (e.g., Perl) to generate the source file for you. Create an array containing all the types you want to specialize, and have it write out the function header for each. You can even embed the script execution in your makefile to automagically re-run it if you change something.
Note: this assumes the implementation of foo
can be made trivial and similar for each type, e.g., simply calling out to the real implementation function. But it avoids a bunch of template/preprocessor mumbo-jumbo that might make a future maintainer scratch his head.
Upvotes: 0
Reputation: 503805
With boost:
#include <boost/type_traits/is_scalar.hpp>
#include <iostream>
#include <string>
namespace detail
{
typedef const boost::true_type& true_tag;
typedef const boost::false_type& false_tag;
template <typename T>
void foo(const T& pX, true_tag)
{
std::cout << "special: " << pX << std::endl;
}
template <typename T>
void foo(const T& pX, false_tag)
{
std::cout << "generic: " << pX << std::endl;
}
}
template <typename T>
void foo(const T& pX)
{
detail::foo(pX, boost::is_scalar<T>());
}
int main()
{
std::string s = ":D";
foo(s);
foo(5);
}
You can mostly easily do it without boost:
#include <iostream>
#include <string>
// boolean stuff
template <bool B>
struct bool_type {};
typedef bool_type<true> true_type;
typedef bool_type<false> false_type;
// trait stuff
template <typename T>
struct is_scalar : false_type
{
static const bool value = false;
};
#define IS_SCALAR(x) template <> \
struct is_scalar<x> : true_type \
{ \
static const bool value = true; \
};
IS_SCALAR(int)
IS_SCALAR(unsigned)
IS_SCALAR(float)
IS_SCALAR(double)
// and so on
namespace detail
{
typedef const true_type& true_tag;
typedef const false_type& false_tag;
template <typename T>
void foo(const T& pX, true_tag)
{
std::cout << "special: " << pX << std::endl;
}
template <typename T>
void foo(const T& pX, false_tag)
{
std::cout << "generic: " << pX << std::endl;
}
}
template <typename T>
void foo(const T& pX)
{
detail::foo(pX, is_scalar<T>());
}
int main()
{
std::string s = ":D";
foo(s);
foo(5);
}
Upvotes: 3
Reputation: 506897
You could use std::numeric_limits
to see whether a type is a numeric type (is_specialized
is true for all float and integer fundamental types).
// small utility
template<bool> struct bool2type { };
// numeric
template<typename T>
void fooImpl(T arg, bool2type<true>) {
}
// not numeric
template<typename T>
void fooImpl(T arg, bool2type<false>) {
}
template<class T>
void foo(T arg)
{ fooImpl(arg, bool2type<std::numeric_limits<T>::is_specialized>()); }
Upvotes: 19
Reputation: 35584
You can use an approach with preprocessor.
foo.inc:
template<>
void foo(TYPE arg)
{ /* do something for int, double, etc. */ }
foo.h:
template<class T>
void foo(T arg)
{ /*do something */ }
#define TYPE int
#include "foo.inc"
#undef TYPE
#define TYPE double
#include "foo.inc"
#undef TYPE
etc.
Upvotes: 3
Reputation: 3208
maybe you can define a default template function that will work on all native type, and delegate specialization of custom type to user
Upvotes: 0