I am specializing template functions when intel intrinsic computation is available. In my case SSE and AVX. I want to produce a test program where I cal the non-specialized template function and the specialized one to compare performance. However, I do not know how to call the non-specialized template function for the type that it is specialized.
Here is a simplified example:
#include <iostream>
template <typename T>
void f(T val)
{
std::cout << "Template function. Value: " << val << std::endl;
}
template <>
void f(float val)
{
std::cout << "Float function. Value: " << val << std::endl;
}
int main()
{
f(1);
f(1.0f);
return 0;
}
Question: is there a way to call f(1.0f) with the non-specialized template function without changing function names?
Clarification: In my case, the two functions are provided in a library as part of the same pair of header and implementation file. Then this is included (for the template) and linked (for the specialization) in the program.
You can add an extra parameter to prohibit specialization:
#include <iostream>
template <typename T, bool enable_specialization = true>
void f(T val)
{
std::cout << "Template function. Value: " << val << std::endl;
}
template <>
void f<float, true>(float val)
{
std::cout << "Float function. Value: " << val << std::endl;
}
int main()
{
f(1.0f);
f<float, false>(1.0f);
return 0;
}
online compiler
Option N°2:
#include <iostream>
template <typename T>
void f(T val)
{
std::cout << "generic" << val << std::endl;
}
void f(float val)
{
std::cout << "Target specific" << val << std::endl;
}
int main()
{
f(1); //=> generic
f(1.0f); //=> target specific
f<float>(1.0f); //=> generic
return 0;
}
Related
A simplified example of my code:
namespace Example
{
class A
{
public:
template<typename T>
void foo(T &val);
template<>
void foo<long>(long &val);
};
template<typename T>
void A::foo(T &val)
{
std::cout << "Generic Function: " << val << std::endl;
}
template<>
void A::foo<long>(long &val)
{
std::cout << "Specialized Function: " << val << std::endl;
}
}
I get an error like:
explicit specialization in non-namespace scope
Why doesn't template specialization work here? How can I specify the behavior of a member function based on the type that's passed in?
You don't need specialization for this, simple overloading will work fine (ie, remove the template<> from the 2nd foo()), eg:
namespace Example
{
class A
{
public:
template<typename T>
void foo(T &val);
void foo(long &val);
};
template<typename T>
void A::foo(T &val)
{
std::cout << "Generic Function: " << val << std::endl;
}
void A::foo(long &val)
{
std::cout << "Specialized Function: " << val << std::endl;
}
}
Online Demo
Or, in C++17 and later, you can just get rid of the 2nd foo() altogether and use if constexpr inside the implementation of the 1st foo(), eg:
#include <type_traits>
namespace Example
{
class A
{
public:
template<typename T>
void foo(T &val);
};
template<typename T>
void A::foo(T &val)
{
if constexpr (std::is_same_v<T, long>)
std::cout << "Specialized Function: " << val << std::endl;
else
std::cout << "Generic Function: " << val << std::endl;
}
}
Online Demo
I was studying about template specialization but unable to understand mixed class and int.
The following code fails to compile click to compile. Can someone suggest the right way here. I wish to specialize for int class. the second template m should be defined as 0 but how to specify that.
#include <iostream>
using namespace std;
template <class T,int m>
void fun(T a )
{
cout << "The main template fun(): " << a << " " << m << endl;
}
template<>
void fun(int a)
{
cout << "Specialized Template for int type: " << a << endl;
}
int main()
{
fun<char,10>('a');
fun<int,20>(10);
fun<float,12>(10.14);
}
The error is:
prog.cpp:11:6: error: template-id 'fun<>' for 'void fun(int)' does not match any template declaration
void fun(int a)
^
I suggest to change order of parameter to let T be deduced, then simply use overload:
template <int m, class T>
void fun(T a )
{
cout << "The main template fun(): " << a << " " << m << endl;
}
template <int m>
void fun(int a)
{
cout << "Template for int type: " << a << endl;
}
With usage:
fun<10>('a');
fun<20>(10);
fun<12, float>(10.14); // or simply fun<12>(10.14f);
I assume that what you're trying to do is to specialise the template so that any call of the form
fun<int, N>(...);
Calls the specialisation?
This would require a partial specialisation of fun() for int, but the C++ language forbids partially specialising function templates. However, we can partially specialise class templates just fine. So one approach to do what you want would be to implement your fun() function using function objects, like so:
// General case
template <typename T, int N>
struct do_fun {
void operator()(T a) {
cout << "The main template fun(): " << a << " " << N << endl;
}
};
// Specialisation for int
template <int N>
struct do_fun<int, N> {
void operator()(int a) {
cout << "Specialized Template for int type: " << a << endl;
}
};
You can then supply a wrapper function template that uses the function objects:
template <typename T, int N>
void fun(T a) {
do_fun<T, N>{}(a);
}
Coliru example
I write a simple code with template and specialization:
#include <iostream>
template <class T>
int HelloFunction(const T& a)
{
std::cout << "Hello: " << a << std::endl;
return 0;
}
template <>
int HelloFunction(const char* & a)
{
std::cout << "Hello: " << a << std::endl;
return 0;
}
int main()
{
HelloFunction(1);
HelloFunction("char");
return 0;
}
I think the char* specialization is correct, but g++ report:
D:\work\test\HelloCpp\main.cpp:11:5:
error: template-id 'HelloFunction<>' for 'int HelloFunction(const char*&)' does not match any template declaration
please help me find the bug.
Function template can be fully specialized and cannot be partially specialized, this is a fact.
That said, the most of the time overloading works just fine and you don't need any specialization at all:
#include <iostream>
template <class T>
int HelloFunction(const T &a) {
std::cout << "Hello: " << a << std::endl;
return 0;
}
int HelloFunction(const char *a) {
std::cout << "Hello: " << a << std::endl;
return 0;
}
int main() {
HelloFunction(1);
HelloFunction("char");
return 0;
}
Non template functions are (let me say) preferred over function templates, thus you can easily got what you pay for in your code with an old plain function.
You can't use the template specialization for function overloading. if this is what you want to do.
Template specialization is meant for specializing the objects and not bare functions. Probably you can change you code something like this to do what you want to do.
template<typename T>
struct ABC {
T type;
ABC(T inType) : type(inType) {}
};
template <class T>
int HelloFunction(ABC<T>& a)
{
std::cout << "Hello: " << a.type << std::endl;
return 0;
}
template <>
int HelloFunction(ABC<const char*> & a)
{
std::cout << "Hello: " << a.type << std::endl;
return 0;
}
int main()
{
HelloFunction(ABC<int>(1));
HelloFunction(ABC<const char*>("char"));
return 0;
}
As you can see from the code above, you use specialization for ABC and using the same in the function HelloFunction
I want to unpack the parameter pack in func (see line A), but it doesnt work. How can I unpack inside func< > or modify Line A only?
#include <iostream>
using namespace std;
void func()
{
cerr << "EMPTY" << endl;
}
template <class A, class ...B> void func()
{
cerr << "A: " << endl;
func<B... >(); // line A
}
int main(void)
{
func<int,int>();
return 0;
}
An expected output :
A:
A:
edited:
all of answers are very good. thanks alot
Sometimes it's easier to unpack everything at once, instead of recursively. If you simply want a parameter pack for_each, you can use a variant of the braced-init-list expansion trick (Live demo at Coliru):
template <class A>
void process_one_type() {
cerr << typeid(A).name() << ' ';
}
template <class ...B> void func()
{
int _[] = {0, (process_one_type<B>(), 0)...};
(void)_;
cerr << '\n';
}
By using func<B... >(); you are implying that func is a function template, but your previously defined func() is not.
You need to define a func() template that accepts zero template arguments. Here's a working example (on g++ 4.8.1):
#include <iostream>
using namespace std;
void func()
{
cerr << "EMPTY" << endl;
}
template <class ... B>
typename std::enable_if<sizeof...(B) == 0>::type func()
{
}
template <class A, class ...B> void func()
{
cerr << "A: " << endl;
func<B... >(); // line A
}
int main(void)
{
func(); // This outputs EMPTY
func<int,int>(); // This will not output EMPTY
return 0;
}
Try this:
template <class A> void func()
{
cerr << "A: " << endl;
}
template <class A, class B, class ...C> void func()
{
cerr << "A: " << endl;
func<B, C...>(); // line A
}
Consider what the invocation of the recursive call func<B...>(); looks like when B... is empty. It's calling func<>(); but the definition of your attempted base case func() is not a template function, ie. you can't call it via func<>();
Since we don't have partial specialization for function templates yet, (hopefully it will be supported soon) one way to do it is to use a class template to do the partial specialization and use the function to simply delegate the work to the class template.
#include <iostream>
/* Forward declaration. */
template <typename... T>
struct FuncImpl;
/* Base case. */
template <>
struct FuncImpl<> {
void operator()() const {
std::cout << "Base case" << std::endl;
}
}; // FuncImpl<>
/* Recursive case. */
template <typename First, typename... Rest>
struct FuncImpl<First, Rest...> {
void operator()() const {
std::cout << "Recursive case" << std::endl;
FuncImpl<Rest...>()();
}
}; // FuncImpl<First, Rest...>
/* Delegate function. */
template <typename... T>
void Func() {
FuncImpl<T...>()();
}
int main() {
Func<>();
Func<int, double>();
}
Personally I think this solution is cleaner than other solutions such as tagged dispatching or SFINAE, despite the cruft around operator()s.
Is it possible to build only some part of the code given the type of the template in C++ ?
It would be something lake that :
#include <iostream>
using namespace std;
template<typename T>
void printType(T param)
{
#if T == char*
cout << "char*" << endl;
#elif T == int
cout << "int" << endl;
#else
cout << "???" << endl;
#endif
}
int main()
{
printType("Hello world!");
printType(1);
return 0;
}
Type traits:
#include <iostream>
#include <type_traits> // C++0x
//#include <tr1/type_traits> // C++03, use std::tr1
template<typename T>
void printType(T param)
{
if(std::is_same<T,char*>::value)
std::cout << "char*" << endl;
else if(std::is_same<T,int>::value)
std::cout << "int" << endl;
else
std::cout << "???" << endl;
}
Or even better yet, just overload the function:
template<class T>
void printType(T partam){
std::cout << "???" << endl;
}
void printType(char* partam){
std::cout << "char*" << endl;
}
void printType(int partam){
std::cout << "int" << endl;
}
Partial ordering will take care that the correct function is called. Also, overloading is preferred to template specialization in the general case, see this and this artice for why. Might not apply for you if you totally have to print the type, as implicit conversions are considered for overloaded functions.
Since C++17 there is a way to do exactly this with if-constexpr. The following compiles since clang-3.9.1, gcc-7.1.0, and recent MSVC compiler 19.11.25506 handles well too with an option /std:c++17.
#include <iostream>
#include <type_traits>
template<typename T>
void printType(T)
{
if constexpr (std::is_same_v<T, const char*>)
std::cout << "const char*" << std::endl;
else if constexpr (std::is_same_v<T, int>)
std::cout << "int" << std::endl;
else
std::cout << "???" << std::endl;
}
int main()
{
printType("Hello world!");
printType(1);
printType(1.1);
return 0;
}
Output:
const char*
int
???
Use template specialization:
template<typename T>
void printType(T param)
{
// code for the general case - or omit the definition to allow only the specialized types
}
template<>
void printType<char*>(char* param)
{
// code for char*
}
template<>
void printType<int>(int param)
{
// code for int
}
// ...
You can use a specialization. The preprocessor runs before all templates and cannot interact with them.
template<typename T> void printType(T t) {
std::cout << typeid(T).name(); // fallback
}
template<> void printType<char*>(char* ptr) {
std::cout << "char*";
}
template<> void printType<int>(int val) {
std::cout << "int";
}
You use template specification to specify versions of your function to work differently based on its type. For example, you can make a generic version of a function that would work with most types, and make a specific version for e.g. int that will be faster. You'd do it this way:
template <class T>
void printType(T param)
{
cout<<"Generic version"<<endl;
}
template <>
void printType<int>(int param)
{
cout<<"Int version"<<endl;
}
template <>
void printType<char>(char param)
{
cout<<"Char version"<<endl;
}
//Rince and repeat.