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
Related
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;
}
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
This is a simple template progs that I wrote to study C++:
#include <type_traits>
#include <iostream>
using namespace std;
template<typename T>
T foo(T t, true_type)
{
cout << t << " is integral! ";
return 2 * t;
}
template<typename T>
T foo(T t, false_type)
{
cout << t << " ain't integral! ";
return -1 * (int)t;
}
template<typename T>
T do_foo(T t){
return foo(t, is_integral<T>());
}
int main()
{
cout << do_foo<int>(3) << endl;
cout << do_foo<float>(2.5) << endl;
}
It doesn't do anything to fancy, but it does compile and work.
I am wondering how does the part is_integral<T>() work?
I was reading this : http://en.cppreference.com/w/cpp/types/is_integral and I can't find any specific description of this behavior - no definition of operator()
is_integral<T> is a type that inherits either from true_type or false_type.
is_integral<T>() is a constructor call, so that an instance of one of those types is an argument to the call to foo. The overload is then selected according to which one it is.
I have to implement template specialization, in implementing the constructor for specialized template class compiler generates some errors. Following is my code:
#include <iostream>
using namespace std;
// class template
template <typename T>
class mycontainer
{
T element;
public:
mycontainer (T arg);
T increase () {return ++element;}
};
// class template specialization
template <>
class mycontainer <void> {
int element;
public:
mycontainer (int arg);
char uppercase ()
{
return element;
}
};
template<typename T> mycontainer<T>::mycontainer(T arg){
cout << "hello T" << endl;
}
template<typename T> mycontainer<void>::mycontainer(int arg){
cout << "hello Empty" << endl;
}
int main () {
mycontainer<int> myint (7);
mycontainer<void> myvoid (6);
cout << myint.increase() << endl;
return 0;
}
The code generate these errors:
test.cpp:31:22: error: prototype for ‘mycontainer<void>::mycontainer(int)’ does not match any in class ‘mycontainer<void>’
test.cpp:16:26: error: candidates are: mycontainer<void>::mycontainer(const mycontainer<void>&)
test.cpp:19:5: error: mycontainer<void>::mycontainer(int)
Any clue on how to resolve these errors ?
Your syntax for full specialization is wrong, you SHOULDN'T use template<typename T> mycontainer<void> or not even template<>
Why? See quote from C++ template book:
A full specialization declaration is identical to a normal class declaration in this way (it is not a template declaration). The only differences are the syntax and the fact that the declaration must match a previous template declaration. Because it is not a template declaration, the members of a full class template specialization can be defined using the ordinary out-of-class member definition syntax (in other words, the template<> prefix cannot be specified):
So can either do
mycontainer<void>::mycontainer(int arg){
cout << "hello Empty" << endl;
}
or do:
#include <iostream>
using namespace std;
// class template
template <typename T>
class mycontainer
{
T element;
public:
mycontainer<T>::mycontainer(T arg)
{
cout << "hello T" << endl;
}
T increase () {return ++element;}
};
// class template specialization
template <>
class mycontainer <void> {
int element;
public:
mycontainer (int arg)
{
cout << "hello Empty" << endl;
}
char uppercase ()
{
return element;
}
};
int main () {
mycontainer<int> myint (7);
mycontainer<void> myvoid (6);
cout << myint.increase() << endl;
return 0;
}
mycontainer<void> is not a template, and neither is its constructor, so the constructor definition should just be:
mycontainer<void>::mycontainer(int arg){
cout << "hello Empty" << endl;
}
Your prototype
template<typename T> mycontainer<void>::mycontainer(int arg){
cout << "hello Empty" << endl;
}
does not match the one in the specialization. Leave the template parameter empty.
That being said: Your C++ does not look like you are ready for using templates. You should get the basics right first.
I would like to specialize a template method for a class C that is itself
templated by an int parameter.
How do I do this?
template <int D=1>
class C {
static std::string foo () { stringstream ss; ss << D << endl; return ss.str();}
};
template <class X>
void test() { cout << "This is a test" << endl;}
template <>
template <int D>
void test<C<D> > () {cout << C<D>::foo() << endl;}
The specialization for test() fails with "Too many template parameter lists in declaration of void test()".
Function template partial specialization is not allowed. Do
template <int D>
void test () {cout << C<D>::foo() << endl;}
You don't want the first template<> on your partial specialisation of test<C<D>>. Moreover, you can only partially specialise class templates, not function templates. Something like this might work:
template <class X>
struct thing
{
static void test() { cout << "This is a test" << endl;}
};
template <int D>
struct thing<C<D>>
{
static void test() {cout << C<D>::foo() << endl;}
};
If your function template took an argument, and used that to infer the template argument, then you could get a similar effect using overloading, something like:
template <class X>
void test(const X&) { cout << "This is a test" << endl;}
template <int D>
void test(const C<D>&) {cout << C<D>::foo() << endl;}
test(3); // calls first version
test(C<3>()); // calls second version