c++ nested template specialization with template class - c++

My problem is as follows.
This is my method:
template<class T>
T my_function();
These specializations work ok:
template<>
int my_function(); //my_function<int>();
template<>
float my_function(); //my_function<flot>();
...
But these don't:
1.
template<>
template<class T>
std::list<T> my_function(); //my_function<std::list<class T> >();
2.
template<class T>
template<>
std::vector<T> my_function(); //my_function<std::vector<class T> >();
I get the error:
too many template-parameter-lists
so my question is:
How do I specialize a template with a template class?

You cannot partially specialize a function template, but you can for class.
So you may forward the implementation to a class as the following:
namespace detail {
template <typename T> struct my_function_caller { T operator() () { /* Default implementation */ } };
template <> struct my_function_caller<int> { int operator() () { /* int implementation */ } };
template <> struct my_function_caller<float> { float operator() () { /* float implementation */ } };
template <typename T> struct my_function_caller<std::list<T>> { std::list<T> operator() () { /* std::list<T> implementation */ } };
template <typename T> struct my_function_caller<std::vector<T>> { std::vector<T> operator() () { /* std::vector<T> implementation */ } };
}
template<class T>
T my_function() { return detail::my_function_caller<T>()(); }

You can't partially specialize a function, if you declare
template<class T>
T my_function() {
....
}
template<class T>
std::list<T> my_function() {
....
}
and try to call the first with
my_function<int>();
since partial specializations are not allowed for functions these declarations will be conflicting (those are actually two different declarations, and what's worse: they both match for that instantiation).
What you can do is wrap your function into a class or a struct that can handle partial specializations for it:
#include <iostream>
#include <list>
using namespace std;
template<class T> struct funWrapper {
T my_function() {
cout << "normal" << endl;
return 0;
}
};
template<class T> struct funWrapper<std::list<T>> {
std::list<T> my_function() {
cout << "stdlist";
return std::list<T>();
}
};
int main() {
funWrapper<int> obj;
obj.my_function();
funWrapper<std::list<int>> obj2;
obj2.my_function();
return 0;
}
http://ideone.com/oIC2Hf

Related

Is there a way to pass templated function signature as a template template parameter

By using template template parameters one can pass to a class a templated class without specifying types on its parameters. I was wondering is there a way to pass into a template template parameter a templated signature of a function to be able to specialize which variant of the function is to be considered forward.
To be clear - I know I cannot do that:
template <class T>
void foo() { /*...*/ }
template <template <class...> class FooType>
struct Foo { /*...*/ };
int main() {
Foo<decltype(foo)> f;
}
But somehow I would like to be able to pass templated signature of function to Foo. Is it even possible?
I couldn't believe that this is not possible so I searched a bit and found a way to do exactly what I wanted. I used templated using with a syntax:
template <template<class... Args> class FooType>
struct Foo {
FooType<int> ft;
};
template <class Res, class... Args>
using FooSignature = Res(*)(Args...);
int foo() {
return 1;
}
int main() {
Foo<FooSignature> f;
f.ft = foo;
}
This however still leaves the question how can this be possible since the standard states something opposite.
In the example below one has a template template parameter that accepts the preferred signature for the function.
Because of the specialization and the lack of a body for the template class, only types for callables are accepted.
It is a generalization of what the OP actually asked:
#include<cassert>
template<typename F>
struct S;
template<typename R, typename... Args>
struct S<R(Args...)> {
using type = R(*)(Args...);
};
template<template<typename> class F>
struct T {
typename F<void(int)>::type ft;
typename F<double(double, double)>::type gt;
};
void f(int) { }
double g(double x, double y) { return x+y; }
int main() {
T<S> t;
t.ft = f;
t.gt = g;
t.ft(42);
auto v = t.gt(1., 1.);
assert(v == 2.);
}
As can be seen in this answer
Template of function pointer is illegal in C++
The C++ Standard says in $14/1,
A template defines a family of classes or functions.
Further quoting from the linked answer:
Please note that it does NOT say "A template defines a family of classes, functions or function pointers"
However, you can pass concrete function pointers, and specialise on their signature:
#include <iostream>
template <class T>
void foo(T) { }
template <typename>
struct Foo;
template<typename T>
struct Foo<void(T)>
{
void cb() { std::cout << "T\n"; }
};
template<>
struct Foo<void(int)>
{
void cb() { std::cout << "int\n"; }
};
template<>
struct Foo<void(double)>
{
void cb() { std::cout << "double\n"; }
};
int main()
{
Foo<decltype(foo<int >)>().cb(); // outputs 'int'
Foo<decltype(foo<double>)>().cb(); // outputs 'double'
Foo<decltype(foo<char >)>().cb(); // outputs 'T'
return 0;
}
template of template is still a template.
template <class T>
void foo() { /*...*/ }
template <typename T>
struct Foo { /*...*/ };
int main() {
Foo<decltype(foo<int>)> f;
}
You cannot pass a function template as an argument. What you can do is wrap a function template in a generate lambda taking a tag parameter:
template <class T> struct tag_t { using type = T; };
template <class T>
void foo() { ... }
template <class F>
void call_func_with(F f) {
f(tag_t<int>{} );
f(tag_t<double>{} );
}
call_with_func([](auto tag) { foo<decltype(tag)::type>(); } );
Here, f(tag_t<X>{} ) ends up calling foo<X>(), as desired.

Mapping instance variables type to template member function

Imagine I have
struct A {
template <class T>
T getFirstElement();
vector<float> floatVector;
vector<int> intVector;
};
in the implelemtation file:
template <>
float A::getFirstElement<float>() {
return floatVector[0];
}
template <>
int A::getFirstElement<int>() {
return intVector[0];
}
Since I know the types of my member variables, even naming them seems overkill. Is there a way to have something (like a typelist) that states at compile time what are the members for this structure? Would like to have something more concise and without explicit template specialization.
With std::tuple you may do
struct A {
template <class T>
T getFirstElement() const
{
return std::get<std::vector<T>>(Vectors)[0];
}
std::tuple<std::vector<float>, std::vector<int>> Vectors;
};
And with variadic template:
template <typename ... Ts>
struct A_impl {
template <class T>
T getFirstElement() const
{
return std::get<std::vector<T>>(Vectors)[0];
}
std::tuple<std::vector<Ts>...> Vectors;
};
struct A : A_impl<float, int> {};
You could write something like:
#include <vector>
template<typename T>
struct VectorProvider
{
std::vector<T> vector;
auto& get() {
return vector;
}
};
struct A
: VectorProvider<float>, VectorProvider<int> {
template <typename T>
T getFirstElement() {
return VectorProvider<T>::get()[0];
}
};
Demo

specializing template member function to work in a different way for a special template class

I have two classes class A and class B both of them are template classes for a member function in A I want it to act in a special way when the type of A is B
and in a normal way for any other types I don't know how to do this ?
template <class B>
class B
{
private:
T m;
public:
...... any member functions
}
template <class T>
class A
{
private:
T var;
public:
void doSomething();
};
template <class T>
void A<T>::doSomething(){...........//implementation}
template <class T>
void A<B<T>>::doSomething(){................//different implementation}
You can specialize A this way:
template <class T>
class A<B<T>> {
// ...
};
This is an instance of partial template specialization.
If you refuse to specialize the entire class, you can defer the work from A<T>::doSomething() to a function doSomethingForA<T>(A &) that would be partially specialized, and that would possibly be friend of A<T>.
Hope this solves your problem:
#include <iostream>
template <typename T>
struct B {};
template <typename T> struct A;
template <typename T>
void doSomething(T&) { std::cout << "General\n"; }
template <typename T>
void doSomething(A<B<T>>&) { std::cout << "Special\n"; }
template <typename T>
struct A {
void doSomething() {
::doSomething(*this);
}
};
int main()
{
A<int> general;
A<B<int>> special;
general.doSomething();
special.doSomething();
}

How to create specialization for a single method in a templated class in C++?

Many questions have been asked and they are similar to the one I am going to ask here, but they are not the same I think.
I have a templated class:
namespace app {
template <typename T>
class MyCLass {
public:
void dosome();
void doother();
}
} /*ns*/
And implementations:
template <typename T>
app::MyClass<T>::dosome() {}
template <typename T>
app::MyClass<T>::doother() {}
When I have an instance of that class to which a char is provided as template parameter, I want function dosome() to behave in a totally different way.
But I just want that function to behave differently, everything else must still act the same.
I tried typing:
template<>
app::MyCLass<char>::dosome() {
}
But the compiler tells me that I am trying to create a specialization in a different namespace.
So when I have a code like this:
app::MyCLass<int> a;
app::MyCLass<char> b;
a.dosome(); // This must call the generic template definition
b.dosome(); // This must call the specialization
a.doother(); // This must call the generic template definition
b.doother(); // This must call the generic template definition
In other questions I saw people creating totally different specialization of the entire class. But I only want a specialization of a single method.
You can do what you want: http://ideone.com/oKTFPC
// Header
namespace My
{
template <typename T>
class MyClass {
public:
void dosome();
void doother();
};
template <typename T> void MyClass<T>::dosome() {}
template <typename T> void MyClass<T>::doother() {}
template<> void MyClass<char>::dosome();
}
// cpp or in header
template<>
void My::MyClass<char>::dosome() {
std::cout << "specialization" << std::endl;
}
or using alternate notation
namespace My {
template<>
void MyClass<char>::dosome() {
std::cout << "specialization" << std::endl;
}
}
One option would be tag dispatching:
template <typename T>
class MyClass {
public:
void dosome() { dosome_impl( T() ); }
private:
void dosome_impl(char) { /* char stuff */ }
template<typename U>
void dosome_impl(U) { /* usual stuff */ }
};
Another one is enable_if idiom:
#include <type_traits>
template <typename T>
class MyClass {
public:
template<typename U = T>
typename std::enable_if<std::is_same<U,char>::value>::type
dosome() { /* char stuff */ }
template<typename U = T>
typename std::enable_if<!std::is_same<U,char>::value>::type
dosome() { /* normal stuff */ }
};
And yet another one is to move that single function to a base class that you can specialize:
template <typename T>
struct MyClass_base {
dosome() { /* usual stuff */ }
};
template<>
struct MyClass_base<char> {
dosome() { /* char stuff */ }
};
template <typename T>
class MyClass : private MyClass_Base<T> {
public:
// nothing special here
};

How to do one explicit specialization for multiple types?

Considering a template function like below how is it possible to do explicitly specialize one version of function for multiple types:
template <typename T>
void doSomething(){
//whatever
}
The intention is to have one specialization instead of multiple following ones because //something is the same:
void doSomething<int>(){
//something
}
void doSomething<float>(){
//something
}
void doSomething<double>(){
//something
}
any method to achieve one specialization?
You can't make template function specialization. But you could delegate the implementation in a helper class, that can be used from your function. Some skeleton code:
Implement a template class and specialize it:
template< typename T, bool isArithmetic>
struct Something { void operator()() { ... } };
template< typename T, true>
struct Something { void operator()() { ... do something specialized for arithmetic types; } }
Then use it in the template function:
template< typename T>
void myFunction()
{
Something<T, IsArithmetic<T>::value>()();
}
Where IsArithmetic is a class that provides the information about type T (selector). You can find such type info in boost libraries, for example.
You could just have a kind of doSomethingImpl function.
template<typename T> doSomethingImpl() {
// whatever
}
template<typename T> doSomething() {
// something else
}
template<> doSomething<float>() {
doSomethingImpl<float>();
}
template<> doSomething<int>() {
doSomethingImpl<int>();
}
It's also possible to specialize more generically, using SFINAE and std::is_numeric<T>, for example.
using c++ 2011 (option -std=c++11), this works well:
#include <iostream>
template <typename T>
struct unsignedObject
{
unsignedObject() {
std::cout << "instanciate a unsignedObject\n";
}
};
struct signedObject
{
signedObject() {
std::cout << "instanciate a signedObject\n";
}
};
template <typename T>
struct objectImpl
{
typedef unsignedObject<T> impl; // optional default implementation (the line can be removed)
};
template <> struct objectImpl<unsigned char> { typedef unsignedObject<unsigned char> impl; };
template <> struct objectImpl<unsigned int> { typedef unsignedObject<unsigned int> impl; };
template <> struct objectImpl<unsigned short> { typedef unsignedObject<unsigned short> impl; };
template <> struct objectImpl<double> { typedef signedObject impl; };
template <> struct objectImpl<int> { typedef signedObject impl; };
template <> struct objectImpl<short> { typedef signedObject impl; };
template <> struct objectImpl<char> { typedef signedObject impl; };
template <typename T>
using object = typename objectImpl<T>::impl;
int main(void)
{
object<int> x; // x is a signedObject.
object<double> y; // y is a signedObject.
object<unsigned short> z; // z is a unsignedObject.
return 0;
}