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
Related
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 have a code, which compiles successfully (g++ 4.9.2):
#include <iostream>
#include <utility>
// general function for any variadic templated argument
template<template<typename ...> class T, typename ...TTs>
void
foo(T<TTs...>& arg)
{
std::cout << "T<TTs...>" << std::endl;
}
template<typename ...Ts>
struct xxx
{
// not important
};
// specialization for only variadic templated xxx
template<typename ...TTs> void
foo(xxx<TTs...>& arg)
{
std::cout << "xxx<TTs...>" << std::endl;
}
// specialization for non-variadic templated xxx
template<typename TT> void
foo(xxx<TT>& arg)
{
std::cout << "xxx<TT>" << std::endl;
}
// specialization for xxx<uint8_t>
template<> void
foo(xxx<uint8_t>& arg)
{
std::cout << "xxx<uint8_t>" << std::endl;
}
int
main(int argc, char** argv)
{
xxx<uint8_t> x1;
std::cout << "xxx<uint8_t> => ";
foo(x1);
xxx<uint16_t> x2;
std::cout << "xxx<uint16_t> => ";
foo(x2);
xxx<uint8_t,uint16_t> x3;
std::cout << "xxx<uint8_t,uint16_t> => ";
foo(x3);
std::pair<uint8_t,uint16_t> x4;
std::cout << "std::pair<uint8_t,uint16_t> => ";
foo(x4);
return 0;
}
and produces:
xxx<uint8_t> => xxx<uint8_t>
xxx<uint16_t> => xxx<TT>
xxx<uint8_t,uint16_t> => xxx<TTs...>
std::pair<uint8_t,uint16_t> => T<TTs...>
Now I want to have these foo methods inside a class, and write:
#include <iostream>
#include <utility>
class abc
{
public:
// general function for any variadic templated argument
template<template<typename ...> class T, typename ...TTs>
void
foo(T<TTs...>& arg)
{
std::cout << "T<TTs...>" << std::endl;
}
};
template<typename ...Ts>
struct xxx
{
// not important
};
// specialization for only variadic templated xxx
template<typename ...TTs> void
abc::foo(xxx<TTs...>& arg)
{
std::cout << "xxx<TTs...>" << std::endl;
}
// specialization for non-variadic templated xxx
template<typename TT> void
abc::foo(xxx<TT>& arg)
{
std::cout << "xxx<TT>" << std::endl;
}
// specialization for xxx<uint8_t>
template<> void
abc::foo(xxx<uint8_t>& arg)
{
std::cout << "xxx<uint8_t>" << std::endl;
}
int
main(int argc, char** argv)
{
abc p;
xxx<uint8_t> x1;
std::cout << "xxx<uint8_t> => ";
p.foo(x1);
xxx<uint16_t> x2;
std::cout << "xxx<uint16_t> => ";
p.foo(x2);
xxx<uint8_t,uint16_t> x3;
std::cout << "xxx<uint8_t,uint16_t> => ";
p.foo(x3);
std::pair<uint8_t,uint16_t> x4;
std::cout << "std::pair<uint8_t,uint16_t> => ";
p.foo(x4);
return 0;
}
and this produces a compilation error:
test_ko.cc:24:1: error: prototype for ‘void abc::foo(xxx<TTs ...>&)’ does not match any in class ‘abc’
abc::foo(xxx<TTs...>& arg)
^
test_ko.cc:10:5: error: candidate is: template<template<class ...> class T, class ... TTs> void abc::foo(T<TTs ...>&)
foo(T<TTs...>& arg)
^
test_ko.cc:31:1: error: prototype for ‘void abc::foo(xxx<TT>&)’ does not match any in class ‘abc’
abc::foo(xxx<TT>& arg)
^
test_ko.cc:10:5: error: candidate is: template<template<class ...> class T, class ... TTs> void abc::foo(T<TTs ...>&)
foo(T<TTs...>& arg)
I want a specialization for foo methods, not declaring a new signature inside abc class (because there is a class with templates, a part of a library, and separate specialization, for later declared xxx class).
It looks for me that code with methods is similar to one with functions, but I get error here. What I do wrong?
// general function for any variadic templated argument
template<template<typename ...> class T, typename ...TTs>
void
foo(T<TTs...>& arg)
{
std::cout << "T<TTs...>" << std::endl;
}
This is a template function.
template<typename ...Ts>
struct xxx
{
// not important
};
// specialization for only variadic templated xxx
template<typename ...TTs> void
foo(xxx<TTs...>& arg)
{
std::cout << "xxx<TTs...>" << std::endl;
}
This is not a specialization. This is a different template function whose name foo overloads with the above template function.
// specialization for non-variadic templated xxx
template<typename TT> void
foo(xxx<TT>& arg)
{
std::cout << "xxx<TT>" << std::endl;
}
This is not a specialization. This is a different template function whose name foo overloads with the above template functions.
// specialization for xxx<uint8_t>
template<> void
foo(xxx<uint8_t>& arg)
{
std::cout << "xxx<uint8_t>" << std::endl;
}
This is a full specialization of one of the above template functions. I think the 3rd one, but I wouldn't bet money on it. (I believe it specializes whichever template xxx<uint8_t>& would be dispatched to if you called foo).
Instead of this full specialization, I would instead write:
inline foo(xxx<uint8_t>& arg)
{
std::cout << "xxx<uint8_t>" << std::endl;
}
which is a brand new overload of foo again. Overloads are far less quirky than full function specializations.
There is no such thing as partial template function specialization.
This explains why your attempt to specialize methods with the same syntax doesn't work. There is no such thing as partial template member function specialization either.
You either have to write the overloads in the class itself, or dispatch to a different context.
What "went wrong" and was the proximate cause of the error is that your initial code introduced new overloads. You are not permitted to introduce new overloads of a method outside of the class definition, so the compiler pointed out your error.
Here is a useful technique. We are in abc:
// general function for any variadic templated argument
template<template<typename ...> class T, typename ...TTs>
void foo(T<TTs...>& arg)
{
return foo(*this, arg);
}
private:
template<template<typename ...> class T, typename ...TTs>
friend void foo(abc& self, T<TTs...>& arg)
{
std::cout << "T<TTs...>" << std::endl;
}
Our foo method extends to a foo friend.
We then add code in the same namespace as abc:
template<typename ...TTs> void
foo(abc& self, xxx<TTs...>& arg)
{
std::cout << "xxx<TTs...>" << std::endl;
}
template<typename TT> void
foo(abc& self, xxx<TT>& arg)
{
std::cout << "xxx<TT>" << std::endl;
}
inline void foo(abc& self, xxx<uint8_t>& arg)
{
std::cout << "xxx<uint8_t>" << std::endl;
}
and they are found via ADL when abc::foo is called.
When playing around with good ol' c++ I started wondering whether it is possible to overload a template function based on an enclosing template. At the first layer this looks achievable, however, how can this be done recursively? So that the below pseudo-c++ code
#include <iostream>
#include <vector>
#include <map>
template <typename T> void magic(){
std::cout << "Called magic<T>" << std::endl;
}
template <typename std::vector<T> > void magic(){
std::cout << "Called magic<std::vector<T> >" << std::endl;
magic<T>();
}
template <typename std::map<T,U> > void magic(){
std::cout << "Called magic<std::map<T,U> >" << std::endl;
magic<T>();
magic<U>();
}
int main() {
magic<std::vector<std::map<std::string,std::vector<int> > > >();
}
yields something like:
Called magic<std::vector<T> >
Called magic<std::map<T,U> >
Called magic<T>
Called magic<std::vector<T> >
Called magic<T>
In principle this does not look like it should be impossible because all the type info is available at compile time. The compiler could easily create all required functions since the recursion is bound to stop. And thus the question: Is this possible? If so, how?
Simple specialization should do the trick, but bear in mind that you cannot specialize function templates partially, so you'll need an intermediate class template:
template <typename> void magic();
template <typename T>
struct Impl
{
static void f() { std::cout << "Primary template\n"; }
};
template <typename T, typename A>
struct Impl<std::vector<T, A>>
{
static void f() { std::cout << "A vector\n"; magic<T>(); }
};
template <typename K, typename T, typename P, typename A>
struct Impl<std::map<K, T, P, A>>
{
static void f() { std::cout << "A map\n"; magic<K>(); magic<T>(); }
};
template <typename T> void magic() { Impl<T>::f(); }
You need partial template specialization, that is a template specialization which itself is a template again.
That is not possible with function templates but it is with classes. So the workaround is to create a class template (here called Magic) with the specializations. Within that class, a simple (non-template) function is called.
Then, a function magic forwards to that class in order to hide that "hack":
Live demo of this code snippet
#include <iostream>
#include <vector>
#include <map>
// Forward declaration of the magic function:
template <typename> void magic();
// General case:
template <typename T>
struct Magic {
static void m(){
std::cout << "Called magic<T>" << std::endl;
}
};
// Vector case:
template <typename T>
struct Magic<std::vector<T> > {
static void m(){
std::cout << "Called magic<std::vector<T> >" << std::endl;
magic<T>();
}
};
// Map case:
template <typename T, typename U>
struct Magic<std::map<T,U> > {
static void m(){
std::cout << "Called magic<std::map<T> >" << std::endl;
magic<T>();
magic<U>();
}
};
// Implementation of the magic function:
template <typename T>
void magic() {
std::cout << "Forwarding..." << std::endl;
Magic<T>::m();
}
int main() {
magic<std::vector<std::map<std::string,std::vector<int> > > >();
}
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.
template <class T, bool flag>
class A
{
//...
void f()
{
std::cout << "false" << std::endl;
}
//...
};
template<class T>
void A<T, true>::f<T, true>()
{
std::cout << "true" << std::endl;
}
The code above is wrong and don't compile, but you get the idea of what I'm going to do. So how should I do that?
You can't specialize just one method of a class. Usually you can solve that with a template nested class on the same T.
template <class T, bool flag>
class A
{
//...
template <class Q, bool flag>
class F_Helper
{
void operator()()
{
std::cout << "false" << std::endl;
}
};
template <class Q>
class F_Helper<Q, true>
{
void operator()()
{
std::cout << "true" << std::endl;
}
};
F_Helper<T> f;
//...
};
Obviously a bit more boilerplate is needed if you do need access to the enclosing class' this pointer.
Contrary to what the other answers say, you can specialize a member function of a class template. But you need to provide all template arguments
template<>
void A<int, true>::f()
{
std::cout << "true" << std::endl;
}
What you try is not valid:
template<typename T>
void A<T, true>::f()
{
std::cout << "true" << std::endl;
}
Partially specializing a member of a class template for particular arguments of that class template is not valid, so that means "define the member function 'f' of a partial specialization of A for <T, true>". Because there is no such partial specialization, the compiler will error out.
If you cannot provide all arguments, you can overload f as follows
template <class T, bool flag>
class A
{
template<typename, bool> struct params { };
void f()
{
f(params<T, flags>());
}
template<typename U>
void f(params<U, true>) {
std::cout << "true" << std::endl;
}
template<typename U, bool flag1>
void f(params<U, flag1>) {
std::cout << "dunno" << std::endl;
}
};
You can specialize whole template class - Ideone link
#include <iostream>
template <class T, bool flag>
class A
{
//...
void f()
{
std::cout << "false" << std::endl;
}
//...
};
template<class T>
class A<T, true>
{
//...
void f()
{
std::cout << "true" << std::endl;
}
//...
};
You need to specialize the whole class:
#include <iostream>
template <class T, bool flag>
class A
{
public:
void f()
{
std::cout << "false" << std::endl;
}
};
template<class T>
class A<T,true>
{
public:
void f()
{
std::cout << "true" << std::endl;
}
};
void main()
{
A<int, false> a;
a.f();
A<int, true> b;
b.f();
}