Home:ALL Converter>One template specialization for multiple classes

One template specialization for multiple classes

Ask Time:2010-03-12T10:04:12         Author:peper0

Json Formatter

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?

Author:peper0,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/2430039/one-template-specialization-for-multiple-classes
Michael Kristofik :

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.\n\nNote: 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.",
2010-03-12T02:28:51
Johannes Schaub - litb :

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).\n\n// small utility\ntemplate<bool> struct bool2type { };\n\n// numeric\ntemplate<typename T>\nvoid fooImpl(T arg, bool2type<true>) {\n\n}\n\n// not numeric\ntemplate<typename T>\nvoid fooImpl(T arg, bool2type<false>) {\n\n}\n\ntemplate<class T>\nvoid foo(T arg)\n{ fooImpl(arg, bool2type<std::numeric_limits<T>::is_specialized>()); }\n",
2010-03-12T02:19:40
Vlad :

You can use an approach with preprocessor.\n\nfoo.inc:\n\ntemplate<>\nvoid foo(TYPE arg)\n{ /* do something for int, double, etc. */ }\n\n\nfoo.h:\n\ntemplate<class T>\nvoid foo(T arg)\n{ /*do something */ }\n\n#define TYPE int\n#include \"foo.inc\"\n#undef TYPE\n\n#define TYPE double\n#include \"foo.inc\"\n#undef TYPE\n\n\netc.",
2010-03-12T02:20:53
GManNickG :

With boost:\n\n#include <boost/type_traits/is_scalar.hpp>\n#include <iostream>\n#include <string>\n\nnamespace detail\n{\n typedef const boost::true_type& true_tag;\n typedef const boost::false_type& false_tag;\n\n template <typename T>\n void foo(const T& pX, true_tag)\n {\n std::cout << \"special: \" << pX << std::endl;\n }\n\n template <typename T>\n void foo(const T& pX, false_tag)\n {\n std::cout << \"generic: \" << pX << std::endl;\n }\n}\n\ntemplate <typename T>\nvoid foo(const T& pX)\n{\n detail::foo(pX, boost::is_scalar<T>());\n}\n\nint main()\n{\n std::string s = \":D\";\n foo(s);\n foo(5);\n}\n\n\nYou can mostly easily do it without boost:\n\n#include <iostream>\n#include <string>\n\n// boolean stuff\ntemplate <bool B>\nstruct bool_type {};\n\ntypedef bool_type<true> true_type;\ntypedef bool_type<false> false_type;\n\n// trait stuff\ntemplate <typename T>\nstruct is_scalar : false_type\n{\n static const bool value = false;\n};\n\n#define IS_SCALAR(x) template <> \\\n struct is_scalar<x> : true_type \\\n { \\\n static const bool value = true; \\\n };\n\nIS_SCALAR(int)\nIS_SCALAR(unsigned)\nIS_SCALAR(float)\nIS_SCALAR(double)\n// and so on\n\nnamespace detail\n{\n typedef const true_type& true_tag;\n typedef const false_type& false_tag;\n\n template <typename T>\n void foo(const T& pX, true_tag)\n {\n std::cout << \"special: \" << pX << std::endl;\n }\n\n template <typename T>\n void foo(const T& pX, false_tag)\n {\n std::cout << \"generic: \" << pX << std::endl;\n }\n}\n\ntemplate <typename T>\nvoid foo(const T& pX)\n{\n detail::foo(pX, is_scalar<T>());\n}\n\nint main()\n{\n std::string s = \":D\";\n foo(s);\n foo(5);\n}\n",
2010-03-12T02:28:17
YeenFei :

maybe you can define a default template function that will work on all native type, and delegate specialization of custom type to user",
2010-03-12T02:10:14
yy