Is there a way to make templated declaration - c++

What I mean is modifying the following code, X declaration to be exact, so that I can use an object B of any kind, B<int>, B<real> ... Sadly, it's important I have an Obj<T> *pobj in B.
template <typename T>
class Obj
{
public:
T a;
public:
Obj(T a_) : a(a_) {}
void print() const
{ std::cout << "a : " << a << std::endl; }
};
template <typename T>
class A
{
public:
Obj<T> *pObj;
public:
A(Obj<T>* pO) : pObj(pO) {}
void doSomethingWithObj()
{ pObj->print(); }
static Obj<double> X;
};
Obj<double> X = Obj<double>(1.0);
template <typename T>
class B : public A<T>
{
public:
B() : A<T>( &X ) {}
void doSmthg()
{ X.print(); }
};
// in main
B<int> b;
b.doSmthg();
That code will return no known conversion for argument 1 from ‘Obj<double>*’ to ‘Obj<int>*’

You might approach it like this:
struct ObjBase
{
virtual void print() const = 0;
};
template <typename T>
class Obj : public ObjBase
{
public:
T a;
public:
Obj(T a_) : a(a_) {}
virtual void print() const
{ std::cout << "a : " << a << std::endl; }
};
template <typename T>
class A
{
public:
ObjBase *pObj;
public:
A(ObjBase* pO) : pObj(pO) {}
void doSomethingWithObj()
{ pObj->print(); }
static Obj<double> X;
};
That is, have a base class that provides an interface for the things that you want to do that are not dependent on the particular type.

Answering myself.
It is ... I forgot the qualification in my tests..
template <typename T>
class A
{
public:
Obj<T> *pObj;
public:
A(Obj<T>* pO) : pObj(pO) {}
void doSomethingWithObj()
{ pObj->print(); }
static Obj<T> X;
};
template<typename T>
Obj<T> Obj<T>::X(1.0);

Related

How to specialize base class template method from derived class?

I'm trying to specialize a base class method from a derived class template, but I'm not sure what would be the proper syntax to achieve it.
For implementation reasons, I need a class structure similar to the one below, but need to specialize func() from the top-level class:
template < typename T >
class BaseTemplate {
public:
BaseTemplate() = default;
virtual ~BaseTemplate() = default;
virtual void func() {
std::cout << __func__ << std::endl;
}
};
class DerivedBase : public BaseTemplate< float > {
public:
DerivedBase() : BaseTemplate() { /* ... */}
virtual ~DerivedBase() = default;
};
template < typename U >
class DerivedTemplate : public DerivedBase {
public:
DerivedTemplate() : DerivedBase() { /* ... */ }
~DerivedTemplate() = default;
protected:
U _member;
};
template < >
void DerivedTemplate< int >::func() {
std::cout << __func__ << " [int]" << std::endl; // error: no member function ‘func’ declared in ‘DerivedTemplate<int>’
}
Additionaly, explicitly declaring using DerivedBase::func; in DerivedTemplate results in another error:
error: template-id ‘func<>’ for ‘void DerivedTemplate<int>::func()’ does not match any template declaration
There is no need to specialize base class function in your case. Since function func() is virtual you can just implement it in one of your derived classes (either in DerivedTemplate or DerivedBase or both if needed):
template < typename U >
class DerivedTemplate : public DerivedBase {
public:
DerivedTemplate() : DerivedBase() { /* ... */ }
~DerivedTemplate() = default;
virtual void func() override {
std::cout << __func__ << "(DerivedTemplate version)" << std::endl;
}
protected:
U _member;
};
Additionaly, explicitly declaring using DerivedBase::func; in
DerivedTemplate results in another error:
error: template-id ‘func<>’ for ‘void DerivedTemplate::func()’
does not match any template declaration
DerivedBase::func; method is defined but not declared. You need to add void func(); in DerivedTemplate.
[Demo]
#include <iostream> // cout
template <typename T>
class BaseTemplate {
public:
BaseTemplate() = default;
virtual ~BaseTemplate() = default;
virtual void func() {
std::cout << __func__ << " [BaseTemplate]\n";
}
};
class DerivedBase : public BaseTemplate<float> {
public:
DerivedBase() : BaseTemplate<float>{} {}
virtual ~DerivedBase() = default;
};
template <typename U>
class DerivedTemplate : public DerivedBase {
public:
DerivedTemplate() : DerivedBase{} {}
~DerivedTemplate() = default;
void func();
};
template <>
void DerivedTemplate<int>::func() {
std::cout << __func__ << " [DerivedTemplate<int>]\n";
}
int main() {
BaseTemplate<char> bt{}; bt.func();
DerivedTemplate<int> dti{}; dti.func();
}
// Outputs:
//
// func [BaseTemplate]
// func [DerivedTemplate<int>]
What you could do in your example is to access BaseTemplate::func from DerivedTemplate<int>.
[Demo]
#include <iostream> // cout
template <typename T>
class BaseTemplate {
public:
BaseTemplate() = default;
virtual ~BaseTemplate() = default;
virtual void func() {
std::cout << __func__ << " [BaseTemplate]";
}
};
class DerivedBase : public BaseTemplate<float> {
public:
DerivedBase() : BaseTemplate<float>{} {}
virtual ~DerivedBase() = default;
};
template <typename U>
class DerivedTemplate : public DerivedBase {
public:
DerivedTemplate() : DerivedBase{} {}
~DerivedTemplate() = default;
void func();
};
template <>
void DerivedTemplate<int>::func() {
BaseTemplate::func();
std::cout << " [int]";
}
int main() {
DerivedTemplate<int> dti{}; dti.func();
}
// Outputs:
//
// func [BaseTemplate] [int]
Also, if you plan to use runtime polymorphism with this hierarchy, you'll want to use virtual void func() override in some of your classes.
[Demo]
#include <iostream> // cout
#include <memory> // make_unique, unique_ptr
template <typename T>
class BaseTemplate {
public:
BaseTemplate() = default;
virtual ~BaseTemplate() = default;
virtual void func() {
std::cout << __func__ << " [BaseTemplate]\n";
}
};
class DerivedBase : public BaseTemplate<float> {
public:
DerivedBase() : BaseTemplate<float>{} {}
virtual ~DerivedBase() = default;
virtual void func() override {
std::cout << __func__ << " [DerivedBase]\n";
}
};
template <typename U>
class DerivedTemplate : public DerivedBase {
public:
DerivedTemplate() : DerivedBase{} {}
~DerivedTemplate() = default;
virtual void func() override {
std::cout << __func__ << " [DerivedTemplate]\n";
}
};
template <>
void DerivedTemplate<int>::func() {
std::cout << __func__ << " [DerivedTemplate<int>]\n";
}
int main()
{
std::unique_ptr<BaseTemplate<float>> dti_up{std::make_unique<DerivedTemplate<int>>()};
dti_up->func();
}
// Outputs:
//
// func [DerivedTemplate<int>]

Polymorphic function call without duplicate code

Suppose that all classes of a hierarchy implement a template member function g. All classes share the same implementation of two other functions f1 and f2 that call this template:
struct A {
virtual void f1() {
g(5);
}
virtual void f2() {
g(5.5);
}
private:
template <typename T> void g(T) {std::cout << "In A" << std::endl;}
};
struct B: A {
// Can I get rid of this duplicate code?
virtual void f1() {
g(5);
}
virtual void f2() {
g(5.5);
}
private:
template <typename T> void g(T) {std::cout << "In B" << std::endl;}
};
struct C: A {
// Can I get rid of this duplicate code?
virtual void f1() {
g(5);
}
virtual void f2() {
g(5.5);
}
private:
template <typename T> void g(T) {std::cout << "In C" << std::endl;}
};
int main()
{
B b;
A &a = b;
a.f1();
return 0;
}
Since the implementations of f1 and f2 are identical in all the classes, how can I get rid of the duplicate code and still have the polymorphic call in main work as expected (i.e produce the output "In B")?
Note that the implementations of f1 and f2 in A, B, and C are not identical. Let's restrict it to f1s. One calls a function named ::A::g<int>, another one calls a function named ::B::g<int>, and the third one calls a function named ::C::g<int>. They are very far from identical.
The best you could do is have a CRTP-style base:
template <class Derived>
struct DelegateToG : public A
{
void f1() override
{
static_cast<Derived*>(this)->g(5);
}
void f2() override
{
static_cast<Derived*>(this)->g(5.5);
}
};
class B : public DelegateToG<B>
{
friend DelegateToG<B>;
private:
template <class T> void g(T) { /*...*/ }
};
class C : public DelegateToG<C>
{
friend DelegateToG<C>;
private:
template <class T> void g(T) { /*...*/ }
};
You can just factor out the class-specific things that the template function uses, such as (in your example) the class name:
#include <iostream>
using namespace std;
class A
{
private:
virtual auto classname() const -> char const* { return "A"; }
protected:
template <typename T> void g(T) {cout << "In " << classname() << endl;}
public:
virtual void f1() { g(5); }
virtual void f2() { g(5.5); }
};
class B
: public A
{
private:
auto classname() const -> char const* override { return "B"; }
};
class C
: public A
{
private:
auto classname() const -> char const* override { return "C"; }
};
auto main()
-> int
{ static_cast<A&&>( B() ).f1(); }

Geting the type from using keyword in derived classes

Consider
struct AbstractClass {};
struct Derived1 : AbstractClass {
using type = int;
};
struct Derived2 : AbstractClass {
using type = char;
};
struct Derived3 : AbstractClass {
using type = bool;
};
int main() {
AbstractClass* a[] = {new Derived1, new Derived2, new Derived3};
}
How to get type from a[0], a[1], a[2]?
Here is what I'm trying to accomplish. I guess there is no other way to do this than this?
#include <iostream>
struct Object { virtual ~Object() = default; };
struct A : Object {};
struct B : Object {};
struct C : Object {};
struct AbstractClass {
virtual void take (Object*) {
std::cout << "Accepted.\n";
}
};
template <typename...> struct ObjectTypes;
template <typename First, typename... Rest>
struct ObjectTypes<First, Rest...> : ObjectTypes<Rest...> {
bool operator()(Object* o) const {
if (dynamic_cast<First*>(o))
return true;
return ObjectTypes<Rest...>::operator()(o);
}
};
template <>
struct ObjectTypes<> {
bool operator()(Object*) const {return false;}
};
struct Derived1 : AbstractClass {
using type = ObjectTypes<A,B>;
virtual void take (Object* o) override {
if (type()(o)) // This is why I want to use type from AbstractClass.
return AbstractClass::take(o);
std::cout << "Rejected.\n";
}
};
struct Derived2 : AbstractClass {
using type = ObjectTypes<A,C>;
virtual void take (Object* o) override {
if (type()(o))
return AbstractClass::take(o);
std::cout << "Rejected.\n";
}
};
struct Derived3 : AbstractClass {
using type = ObjectTypes<B,C>;
virtual void take (Object* o) override {
if (type()(o))
return AbstractClass::take(o);
std::cout << "Rejected.\n";
}
};
int main() {
AbstractClass* abs[] = {new Derived1, new Derived2, new Derived3};
A* a = new A;
B* b = new B;
C* c = new C;
for (AbstractClass* x : abs) {
x->take(a);
x->take(b);
x->take(c);
std::cout << "------------\n";
}
}
Notice the repetitions in Derived1, Derived2, Derived3, etc...? Hence my original goal was to have it all done in the base class AbstractClass.
I rather thought about sth like:
#include <iostream>
struct Object { virtual ~Object() = default; };
struct A : Object {};
struct B : Object {};
struct C : Object {};
struct SuperObjectType {
public:
virtual bool operator()(Object *o) const = 0;
};
template <typename First, typename... Rest>
struct ObjectTypes: SuperObjectType {
bool operator()(Object* o) const override {
if (dynamic_cast<First*>(o))
return true;
return ObjectTypes<Rest...>()(o);
}
};
template <typename OnlyOne>
struct ObjectTypes<OnlyOne>: SuperObjectType {
bool operator()(Object* o) const override {
return dynamic_cast<OnlyOne*>(o);
}
};
struct AbstractClass {
SuperObjectType *sot;
void take (Object* o) {
if ((*sot)(o)) {
std::cout << "ACCEPTED" << std::endl;
} else {
std::cout << "REJECTED" << std::endl;
}
}
};
struct Derived1 : AbstractClass {
Derived1() {
sot = new ObjectTypes<A,B>;
}
};
struct Derived2 : AbstractClass {
Derived2() {
sot = new ObjectTypes<A,C>;
}
};
struct Derived3 : AbstractClass {
Derived3() {
sot = new ObjectTypes<B,C>;
}
};
int main() {
AbstractClass* abs[] = {new Derived1, new Derived2, new Derived3};
A* a = new A;
B* b = new B;
C* c = new C;
for (AbstractClass* x : abs) {
x->take(a);
x->take(b);
x->take(c);
std::cout << "------------\n";
}
}
But I'm happy I've inspired you ;)
Minor alternative to (perhaps) speed up the performance:
template <typename First, typename... Rest>
struct ObjectTypes: ObjectTypes<Rest...> { // Derive from ObjectTypes<Rest...> instead.
virtual bool operator()(Object* o) const override {
if (dynamic_cast<First*>(o))
return true;
return ObjectTypes<Rest...>::operator()(o);
// So now ObjectTypes<Rest...>::operator() can be used, and thus avoid instantiation.
}
};
template <typename T>
struct ObjectTypes<T>: SuperObjectType {
virtual bool operator()(Object* o) const override {
return dynamic_cast<T*>(o);
}
};
Because ObjectTypes<T> is derived from SuperObjectType for any type T, then ObjectTypes<First, Rest...> is derived from SuperObjectType as well (by being derived from ObjectTypes<Last>, were Last is the last type in Rest...). So everything still works (tested).
Solution inspired by Wojciech Frohmberg's suggestion, though I'm not sure this is what he meant. I actually don't know what he meant and I think he meant something else, and would like to see his solution and find out what he was actually saying.
#include <iostream>
struct Object { virtual ~Object() = default; };
struct A : Object {};
struct B : Object {};
struct C : Object {};
template <typename...> struct ObjectTypes;
template <typename First, typename... Rest>
struct ObjectTypes<First, Rest...> : ObjectTypes<Rest...> {
bool operator()(Object* o) const {
if (dynamic_cast<First*>(o))
return true;
return ObjectTypes<Rest...>::operator()(o);
}
};
template <>
struct ObjectTypes<> {
bool operator()(Object*) const {return false;}
};
struct AbstractClass {
virtual void take (Object*) = 0;
template <typename... Ts> void takeHelper (Object* o, ObjectTypes<Ts...>&& types) {
if (types(o)) std::cout << "Accepted.\n"; // And now do whatever with o.
else std::cout << "Rejected.\n";
}
};
template <typename Derived>
struct AbstractClassCRTP : AbstractClass {
virtual void take (Object* o) override {
takeHelper(o, typename Derived::type{});
}
};
struct Derived1 : AbstractClassCRTP<Derived1> {
using type = ObjectTypes<A,B>;
};
struct Derived2 : AbstractClassCRTP<Derived2> {
using type = ObjectTypes<A,C>;
};
struct Derived3 : AbstractClassCRTP<Derived3> {
using type = ObjectTypes<B,C>;
};
int main() {
AbstractClass* abs[] = {new Derived1, new Derived2, new Derived3};
A* a = new A;
B* b = new B;
C* c = new C;
for (AbstractClass* x : abs) {
x->take(a);
x->take(b);
x->take(c);
std::cout << "------------\n";
}
}
Output:
Accepted.
Accepted.
Rejected.
------------
Accepted.
Rejected.
Accepted.
------------
Rejected.
Accepted.
Accepted.

c++ polymorphism : return type of a virtual method

My main class is :
class Data{
public:
Data(std::string name):name_(name){};
virtual ~Data(){};
protected:
std::string name_;
};
Since I'd like to allow any kind of data, I use a template to create my inherited class :
template<typename Type>
class GenericData : public Data{
public:
GenericData(std::string name, Type t);
private:
Type t_;
};
template<typename Type>
GenericData<Type>::GenericData(std::string name, Type t):
Data(name),
t_(t)
{}
The third class is a collection of (Generic)Data :
class Input{
public:
Input();
~Input();
private:
std::vector<Data*> d_;
};
Input::Input(){
d_.push_back(new GenericData("double",3.2);
d_.push_back(new GenericData("int",2);
}
Input::~Input(){
for(unsigned int i(0);i<d_.size();i++){
delete d_[i];
d_[i] = NULL;
}
}
The thing that I don't know how to do is to get the t_ value from from the Input class. I'd like to have a templata<typename Type> Type Input::get(unsigned int i) method that returns t_. I guess that I should create a virtual method in Data and another method in GenericData but I can't make it work.
It's pretty straightforward:
#include <string>
#include <vector>
#include <iostream>
class Data{
public:
Data(std::string name):name_(name){};
virtual ~Data(){};
protected:
std::string name_;
};
template<typename Type>
class GenericData : public Data{
public:
GenericData(std::string name, Type t);
Type Get() { return t_; }
private:
Type t_;
};
template<typename Type>
GenericData<Type>::GenericData(std::string name, Type t):
Data(name),
t_(t)
{}
class Input{
public:
Input() {}
~Input();
void Add(Data*v) {d_.push_back(v);}
template<typename T>
T Get(int i) {
return dynamic_cast< GenericData<T> *>(d_[i])->Get();
}
private:
std::vector<Data*> d_;
};
Input::~Input(){
for(unsigned int i(0);i<d_.size();i++){
delete d_[i];
d_[i] = NULL;
}
}
int main() {
Input inp;
inp.Add(new GenericData<int>("1", 1));
inp.Add(new GenericData<double>("2", 2.0));
std::cout << "1: " << inp.Get<int>(0) << "; 2: " << inp.Get<double>(1) << std::endl;
return 0;
}
That's quite problematic. First of all, you have to provide some way to get it from Data, for example:
(inside GenericData)
public:
T GetValue()
{
// Consider naming t_ more informative
return t_;
}
Secondly, you can create a generic method for getting data in Input:
(inside Input)
public:
template <typename T>
GenericData<T> * GetData(int index)
{
return dynamic_cast<GenericData<T> *>(_d[index]);
}
or, simpler:
(inside Input)
public:
template <typename T>
T GetValue(int index)
{
return (dynamic_cast<GenericData<T> *>(_d[index]))->GetValue();
}

Using the Visitor Pattern with template derived classes

I try to implement the Visitor pattern with templated derived classes
I work with gcc 4.5
here is the VisitorTemplate.hpp, I specialized Derived in the class Visitor, but I'd like to be able to handle any type:
edit : thanks to the suggestions of interjay, the code compiles and runs without errors now
#ifndef VISITORTEMPLATE_HPP_
#define VISITORTEMPLATE_HPP_
#include <iostream>
#include <string>
using namespace std;
template<class T> Derived;
class Visitor
{
public:
virtual void visit(Derived<string> *e) = 0;
};
class Base
{
public:
virtual void accept(class Visitor *v) = 0;
};
template<class T>
Derived: public Base
{
public:
virtual void accept(Visitor *v)
{
v->visit(this);
}
string display(T arg)
{
string s = "This is : " + to_string(arg);
return s;
}
};
class UpVisitor: public Visitor
{
virtual void visit(Derived<string> *e)
{
cout << "do Up on " + e->display("test") << '\n';
}
};
class DownVisitor: public Visitor
{
virtual void visit(Derived<string> *e)
{
cout << "do Down on " + e->display("test") << '\n';
}
};
#endif /* VISITORTEMPLATE_HPP_ */
main.cpp
Base* base = new Derived<string>();
Visitor* up = new UpVisitor();
Visitor* down = new DownVisitor();
base->accept(up);
base->accept(down);
Now my goal is to use Derived in visit without specializing; unfortunately, visit is a virtual method so I can't template it
From Modern C++ - Design Generic Programming and Design Patterns Applied - Andrei Alexandrescu
#include <iostream>
class BaseVisitor
{
public:
virtual ~BaseVisitor() {};
};
template <class T, typename R = int>
class Visitor
{
public:
virtual R visit(T &) = 0;
};
template <typename R = int>
class BaseVisitable
{
public:
typedef R ReturnType;
virtual ~BaseVisitable() {};
virtual ReturnType accept(BaseVisitor & )
{
return ReturnType(0);
}
protected:
template <class T>
static ReturnType acceptVisitor(T &visited, BaseVisitor &visitor)
{
if (Visitor<T> *p = dynamic_cast< Visitor<T> *> (&visitor))
{
return p->visit(visited);
}
return ReturnType(-1);
}
#define VISITABLE() \
virtual ReturnType accept(BaseVisitor &v) \
{ return acceptVisitor(*this, v); }
};
/** example of use */
class Visitable1 : public BaseVisitable<int>
{
/* Visitable accept one BaseVisitor */
public:
VISITABLE();
};
class Visitable2 : public BaseVisitable<int>
{
/* Visitable accept one BaseVisitor */
public:
VISITABLE();
};
class VisitorDerived : public BaseVisitor,
public Visitor<Visitable1, int>,
public Visitor<Visitable2, int>
{
public:
int visit(Visitable1 & c)
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
int visit(Visitable2 & c)
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
int main(int argc, char **argv)
{
VisitorDerived visitor;
Visitable1 visitable1;
Visitable2 visitable2;
visitable1.accept(visitor);
visitable2.accept(visitor);
}
Is possible to avoid dynamic_cast with CRTP pattern like:
#include <iostream>
class BaseVisitor
{
public:
virtual ~BaseVisitor() {};
};
template <class T>
class Visitor
{
public:
virtual void visit(T &) = 0;
};
template <class Visitable>
class BaseVisitable
{
public:
template <typename T>
void accept(T & visitor)
{
visitor.visit(static_cast<Visitable &>(*this));
}
};
/** example of use */
class Visitable1 : public BaseVisitable<Visitable1>
{
};
class Visitable2 : public BaseVisitable<Visitable2>
{
};
class VisitorDerived : public BaseVisitor,
public Visitor<Visitable1>,
public Visitor<Visitable2>
{
public:
void visit(Visitable1 & c)
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
void visit(Visitable2 & c)
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
};
int main(int argc, char **argv)
{
VisitorDerived visitor;
Visitable1 visitable1;
Visitable2 visitable2;
visitable1.accept<VisitorDerived>(visitor);
visitable2.accept<VisitorDerived>(visitor);
}
Your Derived class cannot use Visitor because it hasn't been defined yet (it was only forward declared, and is therefore an incomplete type).
You can fix the compile error by putting the Visitor definition before Derived. You will also need to forward-declare Derived before defining Visitor:
template <class T> class Derived;
class Visitor {
public:
virtual void visit(Derived<string> *e) = 0;
};
template <class T>
class Derived : public Base {
//.... can call Visitor methods here ...
};