I have an interface and a couple of implementations of a class that stores serialized objects. I'd like to make the implementation classes into template classes so I can use them with more than one type of object, but I'm getting compiler errors.
#include <iostream>
template<typename T>
class Interface{
public:
virtual void func(T& c) = 0;
};
class Container{
public:
Container() : dummy(10){}
int dummy;
};
template<typename T>
class Implementation : public Interface{
public:
void func(T& c){
std::cout << "++c.dummy " << ++c.dummy << std::endl;
}
};
int main(){
Container c;
Implementation<Container> i;
i.func(c);
return 0;
}
I get "error: expected class-name before ‘{’ token" at the "class Implementation..." line.
Thanks.
template<typename T>
class Implementation : public Interface<T> {
// ^^^
Related
I have two interfaces that I want to use with CRTP for static polymorphism. One of them contains a function whose types in the signature are implementation-dependent.
This problem looks like what has been asked here without solution. The solution I came up with includes an additional templated structure defining the type. This template is then specialized for the implementation avoiding the "invalid use of incomplete type" error.
Here my code
#include <iostream>
#include <memory>
template<class impl1>
struct Interface1 {
double foo() { return static_cast<impl1*>(this)->fooimpl();}
};
template<class impl1, class impl2>
struct typeHelp;
template<class impl1, class impl2>
struct Interface2 {
void bar(typename typeHelp<impl1,impl2>::type value) {
static_cast<impl2*>(this)->barimpl(value);
}
};
//Implementation2 pre declaration
template<class impl1>
struct Implementation2;
//Partial specialization of templated typeHelp
template<class impl1>
struct typeHelp<impl1, Implementation2<impl1>> {
using type = int;
};
//Implementation2
template<class impl1>
struct Implementation2 : public Interface2<impl1, Implementation2<impl1>> {
std::shared_ptr<Interface1<impl1>> imp1;
void barimpl(typename typeHelp<impl1,Implementation2>::type value) {
std::cout << imp1->foo() << " " << value << std::endl;
}
};
//Implementation1
struct Implementation1 : public Interface1<Implementation1> {
double fooimpl() {return 0.;}
};
int main()
{
Implementation2<Implementation1> obj;
obj.imp1 = std::make_shared<Implementation1>();
obj.bar(4);
}
What I don't like in this code is that Interface2 and typeHelp depend on template parameter impl1. This works for my particular case, where Implementation2 is templated with respect to impl1 but it wouldn't if Implementation2 weren't. I wonder if there is a more general and elegant solution to this problem.
My bad; a little bit more of search and I would have found the answer. On this link, Andy G points out that it is possible to specialize a class template with a templated class. The result is more clean than before
#include <iostream>
#include <memory>
//Interface1.hpp
template<class impl1>
struct Interface1 {
double foo() { return static_cast<impl1*>(this)->fooimpl();}
};
//Interface2.hpp
template<class impl2>
struct typeHelp;
template<class impl2>
struct Interface2 {
void bar(typename typeHelp<impl2>::type value) {
static_cast<impl2*>(this)->barimpl(value);
}
};
//Implementation2.hpp
template<class impl1>
struct Implementation2;
//specialization of typeHelp with templated class
template<class impl1>
struct typeHelp<Implementation2<impl1>> {
using type = int;
};
//Actual implementation of Implementation2
template<class impl1>
struct Implementation2 : public Interface2<Implementation2<impl1>> {
std::shared_ptr<Interface1<impl1>> imp1;
void barimpl(typename typeHelp<Implementation2<impl1>>::type value) {
std::cout << imp1->foo() << " " << value << std::endl;
}
};
//Implementation1.hpp
struct Implementation1 : public Interface1<Implementation1> {
double fooimpl() {return 0.;}
};
//Main.hpp
int main()
{
Implementation2<Implementation1> obj;
obj.imp1 = std::make_shared<Implementation1>();
obj.bar(4);
}
class Base { ... };
class Derived1 : Base { ... };
class Derived2 : Base { ... };
template <> class BaseDecorator<Base> : **SpecificDerived** { ... };
Is it possible for SpecificDerived to reference the particular Derived class that is being used? Such that
BaseDecorator<Derived1> bd-d1;
Would instantiate a BaseDecorator that inherits from Derived1?
The problem has come about because I need to provide a decorator for a library class and all its derivations, but want to keep the code as dry as possible.
Thanks!
If I understood your question correctly, you want your BaseDecorator to inherit from specific Derived class.
If that is the case, You may do something like this:
#include <iostream>
#include <type_traits>
class Base {
public:
virtual void f1() {
std::cout << "Base::f1" << std::endl;
}
};
class Derived1 : public Base {
public:
void f1() override {
std::cout << "Derived1::f1" << std::endl;
}
};
class Derived2 : public Base {
public:
void f1() override {
std::cout << "Derived2::f1" << std::endl;
}
};
class Derived3 {
public:
void f1() {
std::cout << "Derived3::f1" << std::endl;
}
};
template <typename T,
typename = typename std::enable_if<std::is_base_of<Base, T>::value>::type >
class BaseDecorator;
template <typename T>
class BaseDecorator<T>: public T {
public:
void f2() {
T::f1();
}
};
int main() {
BaseDecorator<Derived1> bd1;
bd1.f2();
BaseDecorator<Derived2> bd2;
bd2.f2();
//BaseDecorator<Derived3> bd3; // Compilation fails !!!
//bd3.f2(); // Compilation fails !!!
return 0;
}
Output:
Derived1::f1
Derived1::f2
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 want to find out what is the parent of the type class T in a template function, suppose I've the following classes:
class A{
...
}
class B: public A{
...
}
class C: public B{
...
}
template<typename T>
size_t getBaseHashCode()
{
return typeid(base_of(T)).hashcode();
}
int main()
{
A a;
C c;
size_t size = getBaseHashCode<C>();// must return hashcode of class B
}
is there anyway to find parent of type T and implement base_of function?
Edit:
indeed what I want to do is:
I've factory class which creates objects for me:
template <typename B>
class Factory{
public:
template <typename D>
void registerType(std::string name)
{
static_assert(std::is_base_of<B, D>::value, "class doesn't derive from the base");
table_[name] = &createFunc<D>;
}
B* create(std::string name)
{
const auto it = table_.find(name);
if(it != table_.end())
return it->second();
FILE_LOG(logERROR) << "unidentified option, acceptable options are:";
for(auto const &m : list())
FILE_LOG(logERROR) << '\t' << m;
return nullptr;
}
std::vector<std::string> list()
{
std::vector<std::string> lst;
for(auto const &iter : table_)
lst.push_back(iter.first);
return lst;
}
private:
template<typename D>
static B* createFunc()
{
return new D();
}
typedef B* (*PCreateFunc)();
std::map<std::string, PCreateFunc> table_;
};
in the registerType function I want to set some properties of type D or it's parent and then in the create function, I want to create objects based on that.
You might also consider using some parent wrappers to automatize typedefing:
#include <type_traits>
#include <typeinfo>
#include <iostream>
template <class P>
struct base: P {
using base_type = P;
};
struct A{ };
struct B: base<A>{ };
struct C: base<B>{ };
template <class T>
auto base_of(T) -> typename T::base_type;
template <class T>
using base_of_t = decltype(base_of(std::declval<T>()));
int main() {
std::cout << typeid(base_of_t<C>).name() << std::endl;
}
Output:
1B
Output of c++filt -t 1B:
B
[live demo]
Note it still does not deal with multiple inheritance
You can use a couple of functions declarations that you don't have to define.
It follows a minimal, working example:
#include<utility>
#include<typeinfo>
#include<iostream>
class A{};
class B: public A{};
class C: public B{};
B base_of(const C &);
A base_of(const B &);
template<typename T>
void getBaseHashCode() {
std::cout << typeid(decltype(base_of(std::declval<T>()))).name() << std::endl;
}
int main() {
getBaseHashCode<B>();
getBaseHashCode<C>();
}
It exploits the fact that, in this case, you have exact matches during the invokations. It's quite weak a solution, but works with the example code in the question.
That said, I agree on the fact that the whole question looks like an XY-problem.
EDIT
As mentioned by #Jarod42 in the comments, a more idiomatic (and verbose) way would be by using traits.
It follows a minimal, working example:
#include<typeinfo>
#include<iostream>
class A{};
class B: public A{};
class C: public B{};
template<typename> struct base_of;
template<> struct base_of<B> { using type = A; };
template<> struct base_of<C> { using type = B; };
template<typename T>
void getBaseHashCode() {
std::cout << typeid(typename base_of<T>::type).name() << std::endl;
}
int main() {
getBaseHashCode<B>();
getBaseHashCode<C>();
}
This will solve also the problem due to multiple inheritance. The designer of base_of specializations will be in charge to promote one of the base classes to the role of preferred one.
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;
}