Say I have this template class:
template<typename T> class MyClass{
public:
MyClass(const T& t):_t(t){}
~MyClass(){}
void print(){ cout << _t << endl; }
private:
T _t;
};
And I want to specialize it, so similarly I define:
template<> class MyClass<double>{
public:
MyClass(const double& t):_t(t){}
~MyClass(){}
void print(){ cout << _t << endl; }
private:
double _t;
};
Now, this is ok as long as we're talking about small classes. If I have a very long class, it would be a lot smarter to specialize print() alone. I know how to do it with non-member function. Is there any way to do it with member functions?
In your example, you are using full specialization. In that case, you can do it like this:
template <>
void MyClass<double>::print()
{
cout << _t << endl;
}
but it doesn't work for partial specialization.
One straightforward solution is, define base class template containing things which you want to specialize, and then specialize this class template instead (it would be a small class, after all):
template<typename T>
struct printable
{
protected:
void print(const T & _t) { }
};
template<>
struct printable<double>
{
protected:
void print(const double & _t) { }
};
And then derived from it:
template<typename T>
class MyClass : public printable<T>
{
typedef printable<T> base;
public:
MyClass(T t&):_t(t){}
~MyClass(){}
void print(){ base::print(_t); } //forward
private:
T _t;
};
You don't need to specialize this class template anymore; make it as huge as you want (and reasonable).
Another alternative is policy-based design in which you pass policy-class(es) as template argument(s) to your class template (called host class).
For example,
//lets define few policy classes
struct cout_print_policy
{
template<typename T>
static void print(T const & data)
{
std::cout << "printing using cout = " << data << std::endl;
}
};
struct printf_print_policy
{
static void print(int data)
{
std::printf("printing int using printf = %d\n", data);
}
static void print(double data)
{
std::printf("printing double using printf = %f\n", data);
}
};
//now define the class template (called host class) that
//accepts policy as template argument
template<typename T, typename TPrintPolicy>
class host
{
typedef TPrintPolicy print_policy;
T data;
public:
host(T const & d) : data(d) {}
void print()
{
print_policy::print(data);
}
};
Test code:
int main()
{
host<int, cout_print_policy> ic(100);
host<double, cout_print_policy> dc(100.0);
host<int, printf_print_policy> ip(100);
host<double, printf_print_policy> dp(100.0);
ic.print();
dc.print();
ip.print();
dp.print();
}
Output:
printing using cout = 100
printing using cout = 100
printing int using printf = 100
printing double using printf = 100.000000
Online demo : http://ideone.com/r4Zk4
You can specialize your print member function specially for double:
template< typename T >
class MyClass{
public:
MyClass(T t&):_t(t){}
~MyClass(){}
void print(){}
private:
T _t;
};
template< typename T >
void MyClass< T >::print(){/* your specific implementation*/}
template<>
void MyClass< double >::print(){/* your specific implementation*/}
in class.h
// declaration of template class
template<typename T>
class MyClass
{
public:
MyClass(T t&):_t(t){}
~MyClass(){}
void print(); // general "declaration".
// don't use inline definition for these case
private:
T _t;
};
// specialization "declaration" of wanted member function
template<>
void MyClass<double>::print();
#include "class.inl" // implementation of template class
in class.inl
// general "definition" of wanted member function
template<typename T>
void MyClass<T>::print()
{
cout << _t << endl;
}
in class.cpp
#include "class.h"
// specialization "definition" of wanted member function
// specialization definition of anyone must be here.. not inl file..
void MyClass<double>::print()
{
cout << "double specialization " << _t << endl;
}
Related
I'm creating an Ordered Linked List derived from a Linked List base class, where both are templated. I know because of the Two-Phase name lookup I've got specify that the variables depend on something, like "this->head", "LinkedList::head" or specify "using LinkedList::head" at the beginning. I prefer using the third one, but when there are a lot of members that are going to be inherited, it becomes very verbose. Is there some way to avoid this?
// Here I have the Base Class
template <typename T>
class LinkedList
{
...
public:
...
template <typename TArg> void push_front(TArg&& v0);
template <typename TArg> void push_back(TArg&& v0);
void pop_front();
void pop_back();
void erase(const LinkedList<T>::Iterator& pos);
void clear();
...
protected:
Node<T>* head;
Node<T>* last;
size_t _size;
LinkedList<T>::Iterator _begin;
LinkedList<T>::Iterator _end;
};
And the derived class
// Here I have the derived class
template <typename T>
class OrderedList : public LinkedList<T>
{
using LinkedList<T>::head;
using LinkedList<T>::last;
using LinkedList<T>::_size;
using LinkedList<T>::_begin;
using LinkedList<T>::_end;
using LinkedList<T>::push_back;
using LinkedList<T>::push_front;
using LinkedList<T>::clear;
...
...
public:
...
};
What can I do to deal with that?
This problem is a necessary evil. If we could have done what this question asks, then we would have lost the ability(not sure if its good) to name members in derived class as the same name in base class.
See how this example works.
#include <iostream>
#include <string>
class A {
public:
int member;
virtual void Set(int value) {
member = value;
}
};
class B : public A {
public:
int member;
void Set(int value) override {
member = value;
}
void Show() {
std::cout << "member: " << member << " A::member: " << A::member << "\n";
}
};
int main()
{
B b;
b.Set(5);
b.Show();
}
Is it possible to have callback to member of template class, as depicted above? I mean, I have some template class, there is defined object of another (non-template) class. That object has another member function. I would like to invoke from that member function the member function of template class. Is it feasible?
This is how I understand the problem. A class called 'some_class' (MyAlgorithm) supposed to have a reference to template (AlgorithmConsumer). Since 'some_class' requires only one method, the easiest way is to pass a reference to the function, something like this:
#include <iostream>
#include <functional>
class MyAlgorithm
{
std::function<void()> prepare;
public:
explicit MyAlgorithm(std::function<void()> prepare)
: prepare{prepare}
{}
void do_something()
{
if (prepare)
{
prepare();
}
std::cout << "I did something\n";
}
};
template<typename T>
class AlgorithmConsumer
{
MyAlgorithm algorithm;
public:
AlgorithmConsumer()
: algorithm([this](){prepare();})
{}
void prepare()
{
std::cout << "Preparing...\n";
}
void execute()
{
algorithm.do_something();
}
};
int main()
{
AlgorithmConsumer<int> ac;
ac.execute();
return 0;
}
Hope, this solves your problem.
Here's one way to do it without using std::function
struct B{
template<class T>
void CallTemplateFun(void (T::*funPtr)(), T& instance){
(instance.*funPtr)();
}
};
template<typename T>
class A{
T t;
B b;
public:
A(T v) : t(v){}
void print(){ std::cout << t << std::endl ; }
};
int main(
{
A<int> ai(5);
B b;
b.CallTemplateFun(&A<int>::print, ai);
A<float> af(3.1428f);
b.CallTemplateFun(&A<float>::print, af);
return 0;
}
I want to write class that extends multiple classes by (CRTP).
I can only get Extension<Base<Extension>> my_object; to work.
The api that I want is: Extension<Base> my_object;
How to make this api work?
Thanks.
Test (code is also at godbolt.org):
#include <iostream>
template <template<typename...> class Extension>
class Base1 : public Extension<Base1<Extension>> {
public:
static void beep() { std::cout << "Base1 "; }
};
template <class Plugin>
class Extension1 {
public:
Extension1() : plugin_(static_cast<Plugin*>(this)) {}
void beep() {
plugin_->beep();
std::cout << "Extension1\n";
}
private:
Plugin* plugin_;
};
template <template<typename...> class Plugin>
class Extension2 {
public:
Extension2() : plugin_(static_cast<Plugin<Extension2>*>(this)) {}
void beep() {
plugin_->beep();
std::cout << "Extension2\n";
}
private:
Plugin<Extension2>* plugin_;
};
int main() {
// This works.
Extension1<Base1<Extension1>>b;
b.beep();
// This doesn't work.
Extension2<Base1> c;
c.beep();
return 0;
}
One problem is that the template parameter to Extension2 does not match the signature that Base1 has. Another is that Extension2 does not match the parameter type expected by Base1.
If you change the definition of Extension2 to propertly accept Base1, it itself is still not a candidate to be passed to Base1. You can workaround that with an inner template class that does match what Base1 expects. This inner class would look a lot like Extension1.
template <template<template<typename...> class> class Plugin>
class Extension2 {
template <class P>
struct Inner {
Inner () : plugin_(static_cast<P *>(this)) {}
void beep() { plugin_->beep(); }
private:
P* plugin_;
};
public:
Extension2() {}
void beep() {
plugin_.beep();
std::cout << "Extension2\n";
}
private:
Inner<Plugin<Inner>> plugin_;
};
I am trying to create abstract class which is a template for another classes. Is it possible to create "flexible" template?
Several classes will inherit from this one, all of them will have the functions with the same name, but with different arguments. The abstract class is "Interface" of inheritance classes - I will use pointer of this one to manage another.
For example we have two classes: A and B.
find method of A class needs only type1 type, but the same method of B class needs type1 and type2 types.
This is how I am creating classes that inherit from template:
class A : public Repository<int> {
public void find(int) override; };
class B : public Repository<int, float> {
public void find(int a, float b) override; };
Its all about the part after public keyword. I don't want to type <int, float> to all classes.
I there any way to overload(?) the template<typename type1, typename type2> and the function?
The code of the abstract class.
#ifndef REPOSITORY_HPP
#define REPOSITORY_HPP
#include <string>
//template<typename type1>
template<typename type1, typename type2>
class Repository
{
protected:
typeSTRING name;
public:
virtual void find(type1) = 0;
//virtual void find(type1, type2) = 0;
};
#endif
You would need variadic template in base class, i.e
#include <iostream>
template <typename ... Args>
class Interface
{
public:
virtual void find(Args... args) = 0;
};
class Impl1 : public Interface<int>
{
public:
void find(int value) override
{
std::cout << "found" << value << std::endl;
}
};
class Impl2 : public Interface<int, float>
{
public:
void find(int value, float other_value) override
{
std::cout << "found" << value << " " << other_value << std::endl;
}
};
int main()
{
Impl1 impl1 {};
impl1.find(5);
Impl2 impl2 {};
impl2.find(5, 10.2);
}
To complement the below comment from #KKMKK, this is how you can get an specific type from Args... (from: get the Nth type of variadic template templates?):
template <typename ... Args>
class Interface
{
public:
using FirstType = typename std::tuple_element<0, std::tuple<Args...> >::type;
virtual void add(FirstType) = 0;
virtual void find(Args... args) = 0;
};
class Impl2 : public Interface<int, float>
{
public:
void add(int value) override
{
std::cout << "found" << value << std::endl;
}
void find(int value, float other_value) override
{
std::cout << "found" << value << " " << other_value << std::endl;
}
};
int main()
{
Impl2 impl2 {};
impl2.add(5);
impl2.find(5, 10.2);
}
We would like to specialize member functions of a base class. However, it does not compile. Does anybody know of any alternative that does compile?
Here is an example
struct Base
{
template<typename T>
void Foo()
{
throw "Foo() is not defined for this type";
}
};
struct Derived : public Base
{
template<>
void Foo<int>() { cout << "Foo<int>()" << endl; } // compile error (cannot specialize members from a base class)
template<>
void Foo<double>() { cout << "Foo<double>()" << endl; } // compile error (cannot specialize members from a base class)
};
Eventually, we solved it using overloading.
Here is how the base class looks like
struct Base
{
template<typename T>
class OfType {}
template<typename T>
void Foo(OfType<T>) { static_assert(false, "Foo is not implemented for this type. Please look in the compiler error for more details."); }
};
struct Derived : public Base
{
using Base::Foo;
void Foo(OfType<int>) { // here comes logic for ints }
void Foo(OfType<double>) { // here comes logic for doubles }
};
Here is an example of client code that uses Foo()
template<typename S>
class ClassThatUsesFoo
{
private: S s;
template<typename T>
void Bar(T item)
{
s.Foo(Base::OfType<T>()); // this is the code that uses Foo
DoSomeStuffWithItem(item);
}
};
void main()
{
ClassThatUsesFoo<Derived> baz;
baz.Bar(12); // this will internally use Foo for ints
baz.Bar(12.0); // this will use Foo for doubles
baz.Bar("hello world"); // this will give a verbose compile error
}
This will compile, except for the call to Foo<char>():
#include <iostream>
#include <string>
using namespace std;
struct Base
{
template<typename T>
void Foo()
{
throw "Foo() is not defined for this type";
}
};
struct Derived : public Base
{
template<typename T> void Foo();
};
template<>
void Derived::Foo<int>() { cout << "Foo<int>()" << endl; }
template<>
void Derived::Foo<double>() { cout << "Foo<double>()" << endl; }
int main()
{
Derived derived;
// this is client code
derived.Foo<int>();
derived.Foo<double>();
derived.Foo<char>(); // this throws
}
If you want the call to Foo<char>() -- or any type not specifically specialized by you -- then this works. If you want a non-specialized implementation that works for all types, then you need to add a non-specialized implementation of Foo() as well:
template<typename T>
void Derived::Foo() { cout << "generic" << endl; }
In response to the discussion with Alex (see comments of the answer of John Dibling), this is what I meant (SSCCE):
#include <iostream>
using namespace std;
struct Base
{
template<typename T>
void Foo()
{
//static_assert(false, "Foo() is not defined for this type");
throw "Foo() is not defined for this type";
}
};
// you can add as many specializations in Base as you like
template <>
void Base::Foo<char>() { cout << "Base::Foo<char>()" << endl; }
struct Derived : public Base
{
// just provide a default implementation of Derived::Foo
// that redirects the call to the hidden Base::Foo
template < typename T >
void Foo()
{ Base::Foo<T>(); }
};
// the specializations for Derived
template<>
void Derived::Foo<int>() { cout << "Foo<int>()" << endl; }
template<>
void Derived::Foo<double>() { cout << "Foo<double>()" << endl; }
struct Derived_wo_specialization : public Base
{
/* nothing */
};
int main()
{
Derived d;
d.Foo<char>();
d.Foo<double>();
Derived_wo_specialization dws;
dws.Foo<char>();
dws.Foo<double>();
}