I'm trying to use the static polymorphism and template to create a container that can hold more the one type, from what I know about template it can't be done, but I'm hoping that I'm wrong and there is a way.
I have the following classes:
template<class Derived>
class base
{
public:
base(string);
void clean()
{
cout << "I'm cleannig \n";
}
void process()
{
static_cast<Derived*>(this)->setup();
static_cast<Derived*>(this)->run();
static_cast<Derived*>(this)->cleanup();
}
string name;
};
template<class Derived>
base<Derived>::base(string y):name(y)
{
}
class derived : public base<derived>
{
friend class base<derived>;
void setup() {cout << "derived setup \n"; }
void run() { cout << "derived run \n"; }
void cleanup() { cout << "derived cleanup \n"; }
};
class derived1 : public base<derived1>
{
friend class base<derived1>;
void setup() {cout << "derived1 setup \n"; }
void run() { cout << "derived1 run \n"; }
void cleanup() { cout << "derived1 cleanup \n"; }
};
and I wont to create a container that can hold them, I tried this code -
template <class T>
class Y{
public:
std::vector<base<T>> m_vec;
};
template <typename T>
class D:public Y<T>
{
public:
friend class Y<T>;
void print()
{
for(auto& e: Y<T>::m_vec)
{
e.process();
}
}
};
int main()
{
base<derived>* b = new base<derived>;
base<derived1>* c = new base<derived1>;
D<derived> y;
y.m_vec.push_back(b);
y.m_vec.push_back(c);
y.print();
}
but its not working
i tryed to do this:
y.m_vec.push_back(static_cast<base<derived>>(c));
and I'm getting this error:
error: no matching function for call to ‘std::vector, std::allocator > >::push_back(base*&)’
y.m_vec.push_back(b);
after some testing and digging the answer is that there isn't a way to do it. but you can use std::any like #formerlyknownas_463035818 suggested
declare the std::vector as :
`std::vector<std::any> m_vec;`
Instead of
std::vector<base<T>> m_vec;
and use the boost demangle function to get the type -
std::string name(boost::core::demangle(e.type().name()));
and then use some kind of factory functio to any_cast to the type you need
if(!name.compare("base<derived1>*") )
{
try {
auto* r = any_cast<base<derived1>*>(e);
r->process();
}
catch(const std::bad_any_cast& e) {
std::cout << e.what() << '\n';
}
}
else
{
try {
auto *r = any_cast<base<derived> *>(e);
r->process();
}
catch(const std::bad_any_cast& e) {
std::cout << e.what() << '\n';
}
}
or instead of using the demangle name and use string compare you can use the type() function of the class any and compare is to the typeid like this:
if(e.type()==typeid(base<derived1>*))
Related
A performance bottleneck of my program is frequent calls to functions like following update functions.
Given that flag parameter is always a bool literal, I want to "unroll" the update function to two versions, one with flag=true and one with flag=false, to avoid branch prediction failure.
for normal functions, a bool template parameter can solve this problem easily.
However, template cannot be applied to virtual functions.
I can create two virtual functions manually, but then I have to copy the long code part. It makes futher development harder.
Is there anyway allowing me to write two versions in one function, controlled by a compiling-time constant flag?
#include <iostream>
#include <random>
using std::cout;
using std::endl;
struct Base
{
virtual void update(bool flag) = 0;
};
struct Derived1 : public Base
{
void update(bool flag)
{
if (flag)
{
// some computations
cout << "Derived1 flag=true" << endl;
}
else
{
// some computations
cout << "Derived1 flag=false" << endl;
}
// long code containing several flag-conditioned blocks like the block above
cout << "Derived1" << endl;
}
};
struct Derived2 : public Base
{
void update(bool flag)
{
if (flag)
{
// some computations
cout << "Derived2 flag=true" << endl;
}
else
{
// some computations
cout << "Derived2 flag=false" << endl;
}
// long code containing several flag-conditioned blocks like the block above
cout << "Derived2" << endl;
}
};
int main()
{
Base *p;
srand(time(nullptr));
if (rand() % 2 == 1)
{
p = new Derived1();
}
else
{
p = new Derived2();
}
p->update(false);
p->update(true);
}
Unfortunately, there is no such thing as virtual templates. What can be done however is to create several virtual functions taking an integral (boolean in this particular case) constant, if the flag is really a compile time literal:
#include <iostream>
#include <random>
#include <type_traits>
#include <memory>
using std::cout;
struct Base
{
virtual void updateSeparate(std::true_type) = 0;
virtual void updateSeparate(std::false_type) = 0;
};
struct Derived1 : public Base
{
void updateSeparate(std::true_type)
{
cout << "Derived1 flag=true\n";
updateCommonImpl();
}
void updateSeparate(std::false_type)
{
cout << "Derived1 flag=false\n";
updateCommonImpl();
}
private:
void updateCommonImpl() //or just a static function inside implementation file if members are not used
{
cout << "Derived1\n";
}
};
struct Derived2 : public Base
{
void updateSeparate(std::true_type)
{
cout << "Derived2 flag=true\n";
updateCommonImpl();
}
void updateSeparate(std::false_type)
{
cout << "Derived2 flag=false\n";
updateCommonImpl();
}
private:
void updateCommonImpl() //or just a static function inside implementation file if members are not used
{
cout << "Derived2\n";
}
};
int main()
{
std::unique_ptr<Base> p;
srand(time(nullptr));
if (rand() % 2 == 1)
{
p = std::make_unique<Derived1>();
}
else
{
p = std::make_unique<Derived2>();
}
p->updateSeparate(std::bool_constant<false>{});
p->updateSeparate(std::bool_constant<true>{});
}
DEMO
However, I cannot tell if that will help or maybe hinder the performance even more by making the vtable lookup time even longer, you have to experiment with that by yourself I'm afraid.
I tried to implement a CRTP pattern with constexpr template parameter, please take a look
template<typename T>
struct Base {
template<bool flag>
int update() {
return static_cast<T*>(this)->template updateImpl<flag>();
}
};
struct Derived1 : public Base<Derived1> {
template<bool flag>
constexpr int updateImpl() {
if constexpr (flag) {
return 1;
} else {
return 2;
}
}
};
struct Derived2 : public Base<Derived2> {
template<bool flag>
constexpr int updateImpl() {
return 3;
}
};
int main() {
auto obj1 = new Derived1();
std::cout << obj1->update<true>(); // 1
std::cout << obj1->update<false>(); // 2
auto obj2 = new Derived2();
std::cout << obj2->update<true>(); // 3
std::cout << obj2->update<false>(); // 3
}
I'm a newer of using C++ template and I got trouble with template compiling.
I want to write a similar factory method with template but compiler error says that 'ip is not the member of _FileWriterInfo'. I was confused because it has be defined in NetWriterInfo struct but not in FileWriterInfo. And if I cancel the 'ip' member defination, compiler works. Apparently T param of NetWriter may infer to FileWriterInfo struct by mistake. How can I get rid of it? plz help.
#include <iostream>
#include <string>
enum WriterFormat
{
WTYPE_FILE = 0,
WTYPE_NET = 1
};
typedef struct _FileWriterInfo
{
std::string name;
std::string page;
}FileWriterInfo;
typedef struct _NetWriterInfo
{
std::string name;
std::string ip;
}NetWriterInfo;
template<typename T>
class Writer
{
public:
virtual ~Writer() {}
virtual std::string Write(T info) = 0;
};
template<typename T>
class FileWriter : public Writer<T>
{
public:
std::string Write(T info) override {
std::cout << "name:" << info.name << "\n";
std::cout << "page:" << info.page << "\n";
return info.name;
}
};
template<typename T>
class NetWriter : public Writer<T>
{
public:
std::string Write(T info) override {
std::cout << "name:" << info.name << "\n";
std::cout << "ip:" << info.ip << "\n";
return info.name;
}
};
class Creator
{
Creator() {};
public:
template<typename T>
static Writer<T>* CreateWriter(WriterFormat fmt)
{
Writer<T>* p = nullptr;
if (fmt == WTYPE_FILE)
p = new FileWriter<T>;
if (fmt == WTYPE_NET)
p = new NetWriter<T>;
return p;
}
};
void WriteFile()
{
FileWriterInfo info = { "Hello","100" };
Writer<FileWriterInfo>* w = Creator::CreateWriter<FileWriterInfo>(WTYPE_FILE);
w->Write(info);
return;
}
int main()
{
WriteFile();
return 0;
}
The CreateWriter function instantiates the FileWriter and NetWriter classes with the FileWriterInfo structure. Accordingly, the compiler tries to instantiate the NetWriter::Write function with the type FileWriterInfo, and we get an error.
You can place Write methods directly to FileWriterInfo and NetWriterInfo stuctures (according to the principle of data encapsulation). It also can simplify the code.
It's hard to explain exactly what I want to do here, but I have a base class and two classes which inherit this base class. Both classes which inherit it have their own unique members. I want to be able to pass both to a method, and have that method detect which it is, then access their unique members. I can't assume there will only be two classes which inherit it, so i'm looking for something of a more general solution.
Here is an example of what I'd like to do:
#include <iostream>
class Base {
public:
int _type;
Base() { }
};
class First : public Base {
public:
int _first_only;
First() { }
};
class Second : public Base {
public:
int _second_only;
Second() { }
};
void test (Base b) {
std::cout << "Type: " << b._type << std::endl;
if(b._type==1) {
std::cout << "First\n";
// Want to be able to do this
std::cout << "Val: " << (First)b._first_only << std::endl;
} else if(b._type==2) {
std::cout << "Second\n";
// And this
std::cout << "Val: " << (Second)b._second_only << std::endl;
}
}
int main() {
First f;
f._first_only=1;
f._type=1;
Second s;
s._type=2;
s._second_only=2;
test(f);
test(s);
}
This is similar to others answers:
You can write polymorphic classes to get this behavior using virtual functions.
Pass the Dervied class objects either by pointer or by reference to get polymorphic behaviour. Otherwise it will lead to object slicing. Your test() function leads to object slicing.
This code may also help you. You can see that there are different ways to print the type. I used GetBaseType(), GetDerivedType() and GetType(). Among these GetType() method is convenient for you case. There are two constructors for convenience. Constructors allow to initialize data members.
class Base {
private:
int _type;
public:
Base(int type) : _type(type) { }
int GetBaseType() { return _type; }
virtual int GetDerivedType() = 0;
virtual int GetType() { return _type; }
};
class First : public Base {
private:
int _first_only;
public:
First() : Base(1), _first_only(1) { }
First(int first_only) : Base(first_only), _first_only(first_only) { }
int GetDerivedType() { return _first_only; }
virtual int GetType() { return _first_only; }
};
class Second : public Base {
private:
int _second_only;
public:
Second() : Base(2), _second_only(2) { }
Second(int second_only) : Base(second_only), _second_only(second_only) { }
int GetDerivedType() { return _second_only; }
virtual int GetType() { return _second_only; }
};
void test (Base &b) {
std::cout << "Type: " << b.GetBaseType() << std::endl;
std::cout << "Type: " << b.Base::GetType() << std::endl;
std::cout << "Dervied type: \n";
std::cout << "Val: " << b.GetDerivedType() << std::endl;
std::cout << "Val: " << b.GetType() << std::endl;
}
int main() {
First f(1);
Second s(2);
test(f);
test(s);
First f1;
Second s1;
test(f1);
test(s1);
}
Either declare a virtual function in Base
Move the common members types from First and Second into Base.
For your specific problem, 2nd option is better:
class Base {
public:
int _member; // have getter() method, if '_member' is private
Base() { }
};
Inside, test():
void test (Base &b) { // <--- practice to pass by reference if copy is not needed
// use b._member;
};
Your code does not work polymorphically, because you are passing the function-parameter by value, which results in slicing.
If you have a method that does different things for different types, consider overloading it for each of these types.
Three things I'd do:
In general switching on type codes is not considered good object oriented design: Instead pull the switched code into the classes.
I'd also set up the type tags in the constructor of the specific classes.
And as others have mentioned you need to pass the argument by reference to avoid slicing.
Here's what the code would look like:
#include <iostream>
class Base {
public:
int _type;
Base() { }
virtual void print_to_stream( std::ostream & os ) const =0;
};
class First : public Base {
public:
int _first_only;
First() { _type =1; }
void print_to_stream( std::ostream & os ) const
{
os<<"First\n";
os<<"Val: " << _first_only << std::endl;
}
};
class Second : public Base {
public:
int _second_only;
Second() { _type=2; }
void print_to_stream( std::ostream & os ) const
{
os << "Second\n";
os << "Val: " << _second_only << std::endl;
}
};
void test (Base & b)
{
std::cout << "Type: " << b._type << std::endl;
b.print_to_stream( std::cout );
}
int main() {
First f;
f._first_only=1;
Second s;
s._second_only=2;
test(f);
test(s);
}
I am developing a test-framework. There are a number of test-suites, each is a class with a set of member functions for each individual test.
I would like to find a way to dynamically iterate through all of the tests in a class.
The idealised setup might look something like this:
class A : public Test
{
public:
A() {
addTest(a);
addTest(b);
addTest(c);
}
void a() { cout << "A::a" << endl; }
void b() { cout << "A::b" << endl; }
void c() { cout << "A::c" << endl; }
};
The addTest() method will add its parameter to a list; this list is iterated through at a later point and each method is run.
Is there any way to achieve this? The closest we have come up with so far is this:
class Test
{
public:
template <typename T>
struct UnitTest
{
typedef void (T::*P)();
P f;
UnitTest(P p) : f(p) {}
};
// (this struct simplified: we also include a name and description)
virtual void run(int testId) = 0;
};
class A : public Test
{
public:
A() {
mTests.push_back(UnitTest<A>(&A::a));
mTests.push_back(UnitTest<A>(&A::b));
mTests.push_back(UnitTest<A>(&A::c));
}
void a() { cout << "a" << endl; }
void b() { cout << "b" << endl; }
void c() { cout << "c" << endl; }
// not ideal - this code has to be repeated in every test-suite
void run(int testId)
{
(this->*(mTests[testId].f))();
}
vector<UnitTest<A>> mTests;
};
To invoke one test per-iteration of the main run-loop:
a->run(mTestId++);
This is not ideal because every test-suite (class) has to repeat the run() code and have its own mTests member.
Is there a way to get closer to the ideal?
Make each test a functor or function object. Create a container of pointers to the tests and then iterate over the container:
struct Test_Base_Class
{
virtual bool Execute(void) = 0;
};
typedef std::vector<Test_Base_Class *> Container_Of_Tests;
struct Test_Engine
{
Container_Of_Tests tests_to_run;
void Add_Test(Test_Base_Class * p_new_test)
{
tests_to_run.push_back(p_new_test);
}
void Run_Tests(void)
{
Container_Of_Tests::iterator iter;
for (iter = tests_to_run.begin();
iter != tests_to_run.end();
++iter)
{
(*iter)->Execute(); // Invoke the Execute method on a test.
}
return;
}
}
This is the foundation. I am currently using this pattern but have expanded to include a Resume() method and status reporting.
I have an existing application in C++ with a custom ArrayBase class that manages storage and access to a contiguously allocated region of memory. I have a separate ItrBase class that is used to access data in that ArrayBase. ArrayBase has a createItr() function that currently returns an ItrBase object.
I need to extend ArrayBase to use multiple memory allocations instead of one contiguous one. I have created an EnhancedArray class to do that. For this EnhancedArray to be compatible with the existing application, it's createItr() function must return something that works with the new multiple memory allocations.
So, I have created a derived EnhanceItr class to do this.
My problem is I can't figure out a way for hundreds of code occurrences like this:
ItrBase anIterator = anArray.createItr();
...
double x = anIterator.getData();
to use the EhancedItr's getData() function when anArray is an EnhancedArray.
Here is a simple application illustrating my basic arrangement.
#include <iostream>
using namespace std;
class ItrBase {
public:
ItrBase() { cout << "ItrBase constructor.\n"; };
~ItrBase() { cout << "ItrBase destructor.\n"; };
virtual int vfunc() {return 1;};
};
class EnhancedItr : public ItrBase {
public:
EnhancedItr() { cout << "EnhancedItr constructor.\n"; };
~EnhancedItr() { cout << "EnhancedItr destructor.\n"; };
int vfunc() {return 0;};
};
class ArrayBase {
public:
ArrayBase() { cout << "ArrayBase constructor.\n"; };
~ArrayBase() { cout << "ArrayBase destructor.\n"; };
virtual ItrBase & createItr() {cout << "in AB's createItr()\n"; return *new ItrBase(); };
};
class EnhancedArray : public ArrayBase {
public:
EnhancedArray() { cout << "EnhancedArray constructor.\n"; };
~EnhancedArray() { cout << "EnhancedArray destructor.\n"; };
EnhancedItr & createItr() {cout << "in EA's createItr()\n"; return *new EnhancedItr(); };
};
int main()
{
ArrayBase ab;
EnhancedArray ea;
ItrBase itr = ab.createItr();
ItrBase eitr = ea.createItr(); //EnhancedItr assigned to ItrBase
cout << "ArrayBase's Itr .vfunc(): " << itr.vfunc() <<std::endl;
cout << "EnhancedArray's Itr .vfunc(): " << eitr.vfunc() <<std::endl;
return 0;
}
Both calls to vfunc() above return 1, when I want the second call to return 0.
In main(), I know that if I change the ItrBase types to ItrBase &'s, I do get the desired return types, but then I am modifying my 'existing' code in hundreds of areas, and the destructors for the Iterators are not called.
Is there another strategy that I am not seeing?
Thanks.
Sure, if you're allowed to rewrite ItrBase, then you can use delegation to pass all function calls through to an implementation class, which you hold by pointer or reference so that polymorphism is in effect. This would look a lot like pimpl. And the callers would not have to be written at all, only recompiled.
EDIT: code for those not familiar with pimpl.
struct ItrBase
{
struct ItrImpl
{
virtual ~ItrImpl(){}
virtual int vfunc() = 0;
};
ItrBase(ItrImpl peer) : m_peer(peer) { cout << "ItrBase constructor.\n"; }
~ItrBase() { cout << "ItrBase destructor.\n"; }
int vfunc() { return m_peer->vfunc(); }
private:
const unique_ptr<ItrImpl> m_peer;
};
class ArrayBase
{
struct ItrImpl : public ItrBase::ItrImpl
{
virtual int vfunc() { return 0; }
};
public:
ArrayBase() { cout << "ArrayBase constructor.\n"; };
~ArrayBase() { cout << "ArrayBase destructor.\n"; };
virtual ItrBase createItr() { cout << "in AB's createItr()\n"; return ItrBase(new ItrImpl); };
};
class EnhancedArray : public ArrayBase
{
struct ItrImpl : public ItrBase::ItrImpl
{
virtual int vfunc() { return 1; }
};
public:
EnhancedArray() { cout << "EnhancedArray constructor.\n"; };
~EnhancedArray() { cout << "EnhancedArray destructor.\n"; };
virtual ItrBase createItr() { cout << "in EA's createItr()\n"; return ItrBase(new ItrImpl); };
};
You're running into a problem called slicing: createItr returns a reference, and then you're copying that into an ItrBase by-value. It's as if you did something like this:
EnhancedItr itr1 = ...;
BaseItr itr2 = itr1; // copy by-value
cout << itr2.vfunc(); // prints 1, not 0
You're also leaking memory: createItr returns a newly allocated object, but you're never deleting it. This is very bad, especially since you'd expect array iterators to be used frequently.
completely different thing you can do is use,
BOOST_AUTO(iterator, array);
and let compiler figure out return type.
BOOST_AUTO
Not being up-to-date with the Standard Library, I could not use the unique_ptr<> implementation suggested by Ben Voigt. (version >=4.3) I believe I have taken his concept and implemented it with basic pointers instead. Noting, however, that this implementation is not exception-safe. ItrImpl objects could be left undeleted.
Here's my code. Too bad createItr() has to return a ItrBase object rather than a pointer, otherwise I think I could have gotten auto_ptr<> to work. Output during program execution shows that ~ItrBase() is called only once for each instance, but I am suprised it is not called also during the object return from createItr(). Return value optimization?
#include <iostream>
using namespace std;
struct ItrBase
{
struct ItrImpl
{
virtual ~ItrImpl(){};
virtual int vfunc() const = 0;
};
ItrBase(ItrImpl* peer) : m_peer(peer) { cout << "ItrBase constructor.\n"; };
~ItrBase() { cout << "ItrBase destructor. \n"; delete m_peer; };
int getData() const { return m_peer->vfunc(); };
private:
ItrImpl* const m_peer;
};
class ArrayBase
{
struct ItrImpl : public ItrBase::ItrImpl
{
virtual int vfunc() const { return 0; };
};
public:
ArrayBase() { cout << "ArrayBase constructor.\n"; };
~ArrayBase() { cout << "ArrayBase destructor.\n"; };
virtual ItrBase createItr() { cout << "in AB's createItr()\n"; return ItrBase(new ItrImpl); };
};
class EnhancedArray : public ArrayBase
{
struct ItrImpl : public ItrBase::ItrImpl
{
virtual int vfunc() const { return 1; };
};
public:
EnhancedArray() { cout << "EnhancedArray constructor.\n"; };
~EnhancedArray() { cout << "EnhancedArray destructor.\n"; };
virtual ItrBase createItr() { cout << "in EA's createItr()\n"; return ItrBase(new ItrImpl); };
};
int main()
{
ArrayBase ab;
EnhancedArray ea;
ItrBase itr = ab.createItr();
ItrBase eitr = ea.createItr(); //EnhancedItr assigned to ItrBase
cout << "ArrayBase's Itr .vfunc(): " << itr.getData() <<std::endl;
cout << "EnhancedArray's Itr .vfunc(): " << eitr.getData() <<std::endl;
return 0;
}