C++ Copy construct base class pointer - c++

Searched around and couldn't find any advice to my problem. I'm trying to make a copy constructor for a class that has a private variable that includes a pointer to an Abstract Base Class.
#include "BaseClass.hh"
ClassA::ClassA()
{ }
/* Copy construct a ClassA object */
ClassA::ClassA(const ClassA& obj)
{
std::map<std::string, BaseClass*>::const_iterator it;
//ClassA copy = obj;
for(it = obj.ind.begin(); it != obj.ind.end(); it++)
{
copy.ind[it->first]=(it->second);
}
}
//in .hh file
private:
std::map<std::string, BaseClass*> ind;
Am I even close? If not, how could I fix this?

There are couple of issues here.
++it; repeated in the for loop.
ClassA copy = obj; Once you return from the copy constructor, the variable copy is destroyed. So, you are not doing any copy here.
If you wish to put the value in the map as a pointer, then you need to allocate memory for the pointer variable.
Since you have are having the value in the map as BaseClass pointer, you need to know the exact type you wish to allocate memory for. The key could help here.
I'm taking the liberty of C++11 tag here.This is just for illustration purpose. Take the idea and implement it as it fits your needs. If you observe, I did not release the memory here.Left it for you.
class BaseA
{
public:
virtual void Print() = 0;
};
class Derived1A : public BaseA
{
virtual void Print()
{
std::cout << "Derived1A\n";
}
};
class Derived2A : public BaseA
{
virtual void Print()
{
std::cout << "Derived2A\n";
}
};
std::map<std::string, std::function<BaseA*()>> factory;
class ClassA
{
public:
ClassA()
{
for (auto it = factory.begin(); it != factory.end(); ++it)
{
typedef std::pair<const std::string, BaseA*> Pair;
mapType_m.insert(Pair(it->first, it->second()));
}
}
ClassA(const ClassA& other)
{
for (auto it = other.mapType_m.begin(); it != other.mapType_m.end(); ++it)
{
typedef std::pair<const std::string, BaseA*> Pair;
mapType_m.insert(Pair(it->first, factory[it->first]()));
}
}
void Print()
{
for (auto it = mapType_m.begin(); it != mapType_m.end(); ++it)
{
std::cout << "key:" << it->first << "\tValue:";
it->second->Print() ;
std::cout << "\n";
}
}
private:
std::map<std::string, BaseA*> mapType_m;
};
int main()
{
factory["Derived1A"] = []() { return new Derived1A(); };
factory["Derived2A"] = []() { return new Derived2A(); };
ClassA c1;
ClassA c2 = c1;
c2.Print();
}

Related

CRTP used with std::any vs virtual functions

I am trying to create a compile time polymorphism design that will not require virtual functions with all their drawbacks. However I am struggling with creating simple, effective and easy to understand container that can simulate the ability to hold derived class in it's base class container. My previous attempts with compile time variadic vectors were working, but the code was huge mess. This solutions seems cleaner to me. I have simple code that implements basic CTRP. However I created a runtime container that is storing std::any objects and then based on the type of the object, I can define the action that is supposed to be taken. I have few questions.
How does the usage of std::any and subsequent any_cast<>() hinder the performance compared to the usage of virtual functions?
Is the usage of std::any valid in this situation?
Is there a better way to implement such container?
Is there a way to force implementation as it is with virtual functions (by using virtual <type> foo() = 0)?
Is it a good idea to create an object that will be a CRTP handler? So I will not have a function for CRTP call, but an object, that can manage those calls?
Thank you.
Here is the base class:
class base {
private:
base() = default;
friend T;
T& implementation = static_cast<T&>(*this);
public:
auto do_stuff() {
return implementation.do_stuff();
}
};
Here is the implementation:
#include <iostream>
class implementation_a : public base<implementation_a> {
public:
auto do_stuff() {
std::cout << 42 << std::endl;
}
};
class implementation_b : public base<implementation_b> {
public:
auto do_stuff() {
return 420;
}
};
Here's the container:
#include <vector>
#include <any>
class crtp_vector {
private:
std::vector<std::any> vec;
public:
auto begin() {
return vec.begin();
}
auto end() {
return vec.end();
}
auto empty() {
return vec.empty();
}
auto size() {
return vec.size();
}
void clear() {
vec.clear();
}
void push_back(const std::any& val) {
vec.push_back(val);
}
auto emplace_back(const std::any& val) {
vec.emplace_back(val);
}
};
Here's the main:
#include "crtp_container.h"
#include <utility>
/* crtp call handler */
template <typename T>
auto crtp_call(T& val) {
return val.do_stuff();
}
int main() {
crtp_vector vec;
implementation_a A;
implementation_b B;
vec.push_back(A);
vec.push_back(B);
for(auto &member : vec) {
if(member.type().name() == typeid(implementation_a).name()) {
crtp_call(std::any_cast<implementation_a&>(member));
}
else if(member.type().name() == typeid(implementation_b).name()) {
std::cout << crtp_call(std::any_cast<implementation_b&>(member)) << std::endl;
}
else {
std::cerr << "no viable type conversion" << std::endl;
}
}
return 0;
}
You make it way too complicated. The code shown doesn't use base in any way; nothing would change if you simply remove it entirely. Even though you keep saying "CRTP", you aren't actually relying on CRTP for anything.
The code doesn't use the ability of std::any to hold any type; it's only used to hold one of a fixed set of types known at compile time. std::variant is better for this.
All told, the example boils down to this:
class implementation_a {
public:
auto do_stuff() {
std::cout << 42 << std::endl;
}
};
class implementation_b {
public:
auto do_stuff() {
std::cout << 420 << std::endl;
return 420;
}
};
int main() {
implementation_a A;
implementation_b B;
std::vector<std::variant<implementation_a, implementation_b>> vec;
vec.push_back(A);
vec.push_back(B);
for(auto &member : vec) {
std::visit([](auto& elem) { elem.do_stuff(); }, member);
}
return 0;
}
Demo

Modern iterating c++ collection with filter

Let say I have this class design
class A {};
class B : public A {};
class C : public A {};
and a container of A like this
std::list<A *> elements;
Now what I want to achieve is iterate through all B objects in my container, or, in another time, iterate through all C objects.
The classic way would be
for (auto it = elements.begin(); it != elements.end(); ++it) {
B * b = dynamic_cast<B *>(*it);
if (b) {
// do stuff
}
}
One idea that comes to my mind is creating an iterator class derived from standard that filters but it would be difficult.
No limits on the c++ language level (c++20 may be ok as well but it would be great to see C++11 replies).
Plain c++ and stl please (I know boost has some foreach if construct but).
A possible c++20 implementation using range
#include <iostream>
#include <list>
#include <ranges>
struct A {
virtual ~A() = default;
};
struct B : public A {
void foo() const { std::cout << "B\n"; }
};
struct C : public A {};
int main() {
std::list<A *> demo{new A{}, new B{}, new C{}, new B{}};
auto is_B = [](const A *p) { return dynamic_cast<const B *>(p) != nullptr; };
auto get_B_const = [](const A *p) { return dynamic_cast<const B *>(p); };
for (auto p_B :
demo | std::views::filter(is_B) | std::views::transform(get_B_const)) {
p_B->foo();
}
// demo destruction with delete not shown
}
Prints:
B
B
Demo: https://godbolt.org/z/6oP8hj
Note: if performance matter you can avoid using dynamic_cast two times by
auto get_B_const = [](const A *p) {
assert(dynamic_cast<const B *>(p));
return static_cast<const B *>(p);
};
I can add 2 cents: normally this smells like a design flaw ( sure there are exceptions ), this problem of "heteroganeous container", does not have a "good" solution so far. Something I have seen in th wilds is that on top of std:vector<A*> va with all elements, you may maintain another vector only with "B*" objects, std::vector<B*> vb, when it´s time to iterate go for vb when it´s time to delete go for va
One of the possible solutions without dynamic_cast. But care should be taken to state the correct type in derived class constructors.
And I would recommend to use std::unique_ptr if the list actually stores the class objects.
class Base
{
public:
enum class Type
{
A,
B,
C
};
Base() = delete;
virtual ~Base() = default;
Type type() const { return _type; }
protected:
Base(Type type) : _type{type} {}
private:
Type _type;
};
class A : public Base
{
public:
A() : Base{Base::Type::A} {}
};
class B : public Base
{
public:
B() : Base{Base::Type::B} {}
};
class C : public Base
{
public:
C() : Base{Base::Type::C} {}
};
void function()
{
std::list<std::unique_ptr<Base>> list;
list.emplace_back(std::make_unique<A>());
list.emplace_back(std::make_unique<B>());
list.emplace_back(std::make_unique<C>());
// use non-const iterators if you intend to modify the object
std::for_each(std::cbegin(list), std::cend(list),
[](const auto &item)
{
switch (item->type())
{
case Base::Type::B:
{
assert(dynamic_cast<B*>(item.get()));
const auto &b = static_cast<B*>(item.get());
// do staff with b
break;
}
default:
return;
}
});
}
I think in C++11 the way you described is as close as it gets, but I may be wrong on this. C++17 greatly extended the algorithms library, so you could use std::for_each.
To demonstrate this, let's give the classes a little bit of functionality and create a vector (or list) of instances:
class A {
public:
virtual std::string name() const = 0;
};
class B : public A {
public:
virtual std::string name() const override {
return "Class B";
}
};
class C : public A {
public:
virtual std::string name() const override {
return "Class C";
}
};
int main()
{
std::vector<A*> vec { new B(), new B(), new C(), new C(), new B() };
}
Now using for_each, you could re-write your loop:
std::for_each(std::begin(vec), std::end(vec), [](const A* val) {
auto B* b = dynamic_cast<B*>(val);
if (b)
std::cout << b->name() << std::endl;
});
Unfortunately, there is no builtin filter for any of the algorithms. You could, however, implement something like for_each_if:
template<typename Iterator, typename Predicate, typename Operation> void
for_each_if(Iterator begin, Iterator end, Predicate pred, Operation op) {
std::for_each(begin, end, [&](const auto p) {
if (pred(p))
op(p);
});
}
And use it like this:
for_each_if(std::begin(vec), std::end(vec),
[](A* val) { return dynamic_cast<B*>(val) != nullptr; },
[](const A* val) {
std::cout << val->name() << std::endl;
}
);
Or for your specific case, you could specialize the implementation even more:
template<typename T, typename Iterator, typename Operation> void
dynamic_for_each(Iterator begin, Iterator end, Operation op) {
std::for_each(begin, end, [&](auto p) {
auto tp = dynamic_cast<T>(p);
if (tp)
op(tp);
});
}
and use it like so:
dynamic_for_each<B*>(std::begin(vec), std::end(vec), [](const B* val) {
std::cout << val->name() << std::endl;
});
All three implementations print the same output:
Class B
Class B
Class B
You do not need to cast if you got the design right:
struct A {
virtual void doSomethingWithB() = 0;
virtual ~A() = default;
};
struct B : A {
void doSomethingWithB() override {
// do somehting
}
};
struct C : A {
void doSomethingWithB() override {
// do nothing !
}
};
Then your loop is simply:
for (auto elem : elements) {
elem->doSomethingWithB();
}

How can I maintain polymorphism when creating an instance on stack in C++?

To create instance on the heap and maintain polymorphism, and that'll give the right answer:
class Father
{
public:
virtual void Say()
{
cout << "Father say hello" << endl;
}
};
class Son : public Father
{
public:
void Say()
{
cout << "Son say hello" << endl;
}
};
int main()
{
std::vector<Father*> v;
std::cout << 1 << std::endl;
for(int i(0); i<5; i++)
{
auto p = new Son(); ---------------on heap
v.emplace_back(p);
}
for(auto p : v)
{
p->Say();
}
}
But when I want to create an instance on the stack, it seems not so easy:
Edition 1:
class Father
{
public:
virtual void Say()
{
cout << "Father say hello" << endl;
}
};
class Son : public Father
{
public:
void Say()
{
cout << "Son say hello" << endl;
}
};
int main()
{
std::vector<Father> v;
for(int i(0); i<5; i++)
{
auto o = Son(); ---------------on stack
v.emplace_back(o);---------------now "o" is cast to Father type
}
for(auto o : v)
{
o.Say();------------------------only output "Father say hello"
}
}
And edition 2:
class Father
{
public:
virtual void Say()
{
cout << "Father say hello" << endl;
}
};
class Son : public Father
{
public:
void Say()
{
cout << "Son say hello" << endl;
}
};
int main()
{
std::vector<Father*> v;
for(int i(0); i<5; i++)
{
auto p = &Son(); --------------On the stack
v.emplace_back(p);---------------Now "o" is cast to Father type
}
for(auto p : v)
{
p->Say();------------------------Since "p" now is a Wild pointer, it'll fail too
}
}
Can this be fixed? Or is it just a dead end: If I want to use polymorphism, then I have to create an object on the heap.
In general polymorphism does not require dynamic allocations. That's a common misunderstanding, and hence here comes a counter example:
void foo(const Father& f) { f.Say(); }
Son s;
foo(s);
You have to declare Say as const to make it work, but then it will print the expected Son say hello. You need references or pointers for polymorphism, not necessarily dynamic allocation!
Having said this, when you want a container of derived classes, then std::vector<Father> won't do. Public inheritance models a "is-a" relation, so a Son is a Father, but a Father is not a Son (notice how wrong and misleading the father-son analogy is?!?). Hence when you put a Son into a vector of Fathers, then the object gets sliced and only the Father part is stored in the vector (read about "object slicing").
Moreover, auto p= &Son(); is wrong, because the created object is temporary and its life time ends at the end of that line. The pointer you store in the vector is dangling (it points to an object whose lifetime already ended).
To store pointers in the container you can use dynamic allocations. For example, with std::unique_ptrs:
int main()
{
std::vector<std::unique_ptr<Father>> v;
for(int i(0);i<5;i++){
v.emplace_back(new Son);
}
for(auto& p:v){
p->Say();
}
}
Note that you have to use auto& for the range based for loop, because unique_ptr doesn't copy. unique_ptr does the dirty work: the objects will get deleted automatically when the unique_ptrs get destroyed (which is when the vector goes out of scope).
This is a recurring problem/dilemma: you can maintain a value semantic at the expense of some boilerplate code. Here is a minimal working example of such kind of idea:
#include <iostream>
#include <memory>
#include <vector>
class Father
{
protected:
struct Father_Interface
{
virtual void
Say() const
{
std::cout << "Father say hello" << std::endl;
}
};
using pimpl_type = std::shared_ptr<const Father_Interface>;
pimpl_type _pimpl;
Father(const Father_Interface* p) : _pimpl(p) {}
public:
Father() : Father{new Father_Interface{}} {}
void Say() const { _pimpl->Say(); }
};
class Son : public Father
{
protected:
class Son_Interface : public Father_Interface
{
void
Say() const override
{
std::cout << "Son say hello" << std::endl;
}
};
public:
Son() : Father{new Son_Interface{}} {}
Son& operator=(const Father&) = delete; // fight against object slicing
};
int
main()
{
std::vector<Father> v;
v.emplace_back(Father());
v.emplace_back(Son());
v.emplace_back(Father());
for (const auto& v_i : v)
{
v_i.Say();
}
}
which prints:
Father say hello
Son say hello
Father say hello
You can also read about:
Sean Parent's better-code-runtime-polymorphism
discussion about its usage
There are lots of things you are doing wrong. First here is how you can do it right:
int main()
{
Father father1;
Son son1;
Father father2;
Son son2;
std::vector<Father*> v;
v.emplace_back(&father1);
v.emplace_back(&son1);
v.emplace_back(&father2);
v.emplace_back(&son2);
for (auto p : v) {
p->Say();
}
}
Basically you need to allocate the objects on the stack so that the objects will be available for as long as the vector is.
Now what you did is undefined behavior, because you basically had pointers (in the vector) to objects that were already de-allocated (even if you fix what was already said in the comments).
for(int i(0);i<5;i++){
Son s;
v.emplace_back(&s);
// s lifetime end here, but the vector still has pointers to objects that are de-allocated
}
For this bit: v.emplace_back(p);---------------now "o" is cast to Father type.
I think you tried something completely different: a vector of Father objects std::vector<Father> and if you try to add Son elements into that you get object slicing // I just added this bit so that you can look it up, this is not the main point here
The question doesn't have much to do with stack. You're really asking how to implement polymorphism when storing by value. It's not too hard if you can use C++17 and thus have std::variant available.
The implementation is surprisingly simple:
#include <algorithm>
#include <cassert>
#include <variant>
#include <vector>
enum class Who { Father, Son };
struct ISayer {
virtual Who Me() const = 0;
virtual ~ISayer() {};
};
struct Father final : ISayer {
Who Me() const override { return Who::Father; }
};
struct Son final : ISayer {
Who Me() const override { return Who::Son; }
};
struct AnySayer0 : std::variant<Father, Son>
{
using variant_type = std::variant<Father, Son>;
using variant_type::variant;
operator const ISayer &() const {
return std::visit([](auto &val) -> const ISayer &{ return val; },
static_cast<const variant_type &>(*this));
}
operator ISayer &() {
return std::visit([](auto &val) -> ISayer &{ return val; },
static_cast<variant_type &>(*this));
}
const ISayer *operator->() const { return &static_cast<const ISayer &>(*this); }
ISayer *operator->() { return &static_cast<ISayer &>(*this); }
};
using AnySayer = AnySayer0;
int main()
{
std::vector<AnySayer> people;
people.emplace_back(std::in_place_type<Father>);
people.emplace_back(std::in_place_type<Son>);
assert(people.front()->Me() == Who::Father);
assert(people.back()->Me() == Who::Son);
}
An alternate implementation AnySayer1 would need a bit more boilerplate, and perhaps be a bit faster - but would it be a bit smaller as well?
struct AnySayer1
{
template <typename ...Args>
AnySayer1(std::in_place_type_t<Father>, Args &&...args) :
father(std::forward<Args>(args)...), ref(father) {}
template <typename ...Args>
AnySayer1(std::in_place_type_t<Son>, Args &&...args) :
son(std::forward<Args>(args)...), ref(son) {}
~AnySayer1() { ref.~ISayer(); }
operator const ISayer &() const { return ref; }
operator ISayer &() { return ref; }
const ISayer *operator->() const { return &static_cast<const ISayer &>(*this); }
ISayer *operator->() { return &static_cast<ISayer &>(*this); }
AnySayer1(AnySayer1 &&o) : ref(getMatchingRef(o)) {
if (dynamic_cast<Father*>(&o.ref))
new (&father) Father(std::move(o.father));
else if (dynamic_cast<Son*>(&o.ref))
new (&son) Son(std::move(o.son));
}
AnySayer1(const AnySayer1 &o) : ref(getMatchingRef(o)) {
if (dynamic_cast<Father*>(&o.ref))
new (&father) Father(o.father);
else if (dynamic_cast<Son*>(&o.ref))
new (&son) Son(o.son);
}
AnySayer1 &operator=(const AnySayer1 &) = delete;
private:
union {
Father father;
Son son;
};
ISayer &ref;
ISayer &getMatchingRef(const AnySayer1 &o) {
if (dynamic_cast<const Father *>(&o.ref))
return father;
if (dynamic_cast<const Son *>(&o.ref))
return son;
assert(false);
}
};
This could be rewritten using the same "magic" that makes std::variant work - it'd be less repetitive that way.
But - is it smaller?
static_assert(sizeof(AnySayer1) == sizeof(AnySayer0));
No. At least in both gcc and clang, both implementations have the same size. And that makes sense, since std::variant doesn't need to store any more information than we do - it only needs to keep some way to discriminate the type. We chose to use the reference to ISayer and use dynamic type information, since that optimizes for the common case when we convert to the interface type - we store the reference ready to use. std::variant can't assume that the types have a common base, and instead stores an integer type index instead and uses generated code to dispatch on that index. It may be generally a bit slower in the path that uses the visitor to return the reference - but not necessarily, since the compiler can note that both types have their ISayer vtable pointer at the same location, and can squash the type-based dispatch down to a "has value vs has no value" test. It seems that the most recent versions of all major C++ compilers (gcc, clang and MSVC) easily deal with this and generate code that is just as fast as our "optimized" AnySayer1.

Template type of class in inheritance

Let's say I have class Action
template<class T>
class Action {
public:
virtual ~Action() = default;
virtual void execute(T &object) const = 0;
};
which can be executed on some object of type T
Next, I have class Object
class Object {
public:
Object() : actions() {}
virtual ~Object() = default;
virtual const std::string getName() const = 0;
void addAction(const Action<Object> *action) {
actions.push_back(action);
}
void execute() {
for (auto &action : actions) {
action->execute(*this);
}
}
private:
std::vector<const Action<Object> *> actions;
};
which holds a vector of actions which can be executed at once.
Now, I have some concrete ObjectA
class ObjectA : public Object {
public:
const std::string getName() const override {
return "ObjectA";
}
};
and two concrete actions ActionA, ActionB
class ActionA : public Action<ObjectA> {
void execute(ObjectA &object) const override {
std::cout << "ActionA on " << object.getName() << std::endl;
}
};
class ActionB : public Action<ObjectA> {
void execute(ObjectA &object) const override {
std::cout << "ActionB on " << object.getName() << std::endl;
}
};
The usage is that I create an ObjectA, add both action to it and execute them.
int main() {
ObjectA object = ObjectA{};
object.addAction(reinterpret_cast<const Action<Object> *>(new ActionA()));
object.addAction(reinterpret_cast<const Action<Object> *>(new ActionB()));
// This is what I want to achieve instead of using reinterpret_cast
//object.addAction(new ActionA());
//object.addAction(new ActionB());
object.execute();
}
The output should be
ActionA on ObjectA
ActionB on ObjectA
The problem is that in order to compile it, I must use reinterpret_cast. The problem is probably the definition of std::vector<const Action<Object> *> actions; I would like to template this, so in ObjectA it is like std::vector<const Action<ObjectA> *> actions;
Is something like that possible?
Action<Object> and Action<ObjectA> are unrelated types in the C++ type system.
What more, Action<Object> permits itself to be called with more types than Action<ObjectA>. So ignoring the type system, an Action<ObjectA> cannot implement the contract that Action<Object> promises it can fulfill.
However, an Action<Object> can fulfill the promise that an Action<ObjectA> makes.
There are famous two kinds of OO-type relations; covariance and contravariance. Action<T> is cotravariant in T, Action<Base> can be used to fulfill the contract of Action<Derived>.
So an approach.
First, your Action<T> is a poorly written pointer-semantic version of std::function<void(T&)>. Use that instead.
You now have value semantics.
template<class T>
using Action=std::function<void(T&)>;
class Object {
public:
Object() = default;
virtual ~Object() = default;
virtual const std::string getName() const = 0;
void addAction(Action<Object> action) {
actions.emplace_back(std::move(action));
}
void execute() {
for (auto &action : actions) {
action(*this);
}
}
private:
std::vector<Action<Object>> actions;
};
ah, much nicer.
This doesn't, however, solve your problem.
auto ActionA = Action<ObjectA>{
[](ObjectA &object) {
std::cout << "ActionA on " << object.getName() << std::endl;
}
};
ActionA cannot be assigned to an Action<Object> because an Action<Object> can be passed a non-ObjectA and it must do something with it.
Your original code's override won't compile.
We have to decide if we want to pretend to be an Action<Object> what we should do if the types mismatch? Here is one option:
template<class T, class F>
auto only_when_dynamic_type_matches( F&& f ) {
if constexpr( std::is_pointer< T >{} ) {
return
[f=std::forward<F>(f)](auto* x)->void{
auto* t = dynamic_cast<T>(x);
if (!t) return
f(t);
};
} else {
return
[f=std::forward<F>(f)](auto&& x)->void{
auto* t = dynamic_cast<std::remove_reference_t<T>*>(std::addressof(x));
if (!t) return;
f(*t);
};
}
}
now we can write
auto ActionA = only_when_dynamic_type_matches<ObjectA&>([](auto&&object) {
std::cout << "ActionA on " << object.getName() << std::endl;
});
auto ActionB = only_when_dynamic_type_matches<ObjectA&>([](auto&&object) {
std::cout << "ActionB on " << object.getName() << std::endl;
});
then
int main() {
ObjectA object = ObjectA{};
object.addAction(ActionA);
object.addAction(ActionB);
object.execute();
}
Live example.

C++ Cartesian product iterator calling base class function on first iteration

I'm working on a set of n-dimension Cartesian product classes, loosely based off of this solution.
I have many different data types for the same basic set of algorithms and I thought "Aha! I will use templates to lessen my overall work!" And, up until now, it's been working awesome. I'm using Boost's iterator_facade.
My problem is with a derived class I made to work with map<char, boost::integer_range<int> >. Each iteration yields a map<char,int>, but I exclude pairs with a second value of 0 as they're just wasted space as far as my algorithms are concerned.
The derived class overloads the function that generates the iterator's return value and it works. However, during the first iteration, the base class's generator is called. I'm much confused. Does anyone have any ideas?
Here are the relevant code snippets:
#include <boost/container/flat_map.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/range/irange.hpp>
#include <utility>
#include <iostream>
using namespace boost;
using namespace boost::tuples;
using namespace std;
template <class Container2DMap,
class return_type = boost::container::flat_map<typename Container2DMap::value_type::first_type,
typename Container2DMap::value_type::second_type::value_type> >
class CartProductIterator2DMap : public boost::iterator_facade<
CartProductIterator2DMap<Container2DMap, return_type>,
const return_type,
boost::forward_traversal_tag> {
public:
typedef typename Container2DMap::value_type::first_type first_type;
typedef typename Container2DMap::const_iterator first_iterator;
typedef typename Container2DMap::value_type::second_type::value_type second_type;
typedef typename Container2DMap::value_type::second_type::const_iterator second_iterator;
CartProductIterator2DMap(const Container2DMap &container) {
rangeIterSetup(container);
}
CartProductIterator2DMap() : _finished(true) {}
virtual ~CartProductIterator2DMap() {}
private:
virtual bool equal(const CartProductIterator2DMap &other) const {
if (_finished || other._finished) {
if (_finished && other._finished) {
return true;
} else {
return false;
}
} else if (_currentIter == other._currentIter) {
return true;
} else {
return false;
}
}
virtual void increment() { advance(); }
virtual void advance() {
advanceIter();
}
virtual const return_type& dereference() const { return _currentIter; }
protected:
struct mode {
const static bool stopIter = false;
const static bool continueIter = true;
};
typedef boost::tuple<second_iterator,
second_iterator,
second_iterator> SecondIterDescription;
typedef boost::container::flat_map<first_type, SecondIterDescription> RangeIterMap;
friend class boost::iterator_core_access;
return_type _currentIter;
RangeIterMap _rangeIter;
bool _finished;
bool _iterMode;
virtual void advanceIter() {
if (_iterMode == mode::continueIter) {
_currentIter = genReturnValue(_rangeIter);
_iterMode = advanceRangeIter(_rangeIter);
} else {
_finished = true;
}
}
virtual void rangeIterSetup(const Container2DMap &container) {
_finished = false;
if (container.empty()) {
_iterMode = mode::stopIter;
} else {
_iterMode = mode::continueIter;
for (typename Container2DMap::const_iterator it = container.begin();
it != container.end(); ++it) {
_rangeIter.insert(
make_pair(it->first,
SecondIterDescription(it->second.begin(), it->second.end(), it->second.begin())
)
);
}
advance();
}
}
virtual return_type genReturnValue(const RangeIterMap &rangeIter) {
std::cout << "Calling base class." << std::endl;
return_type returnValue;
for( typename RangeIterMap::const_iterator it = rangeIter.begin();
it != rangeIter.end(); ++it) {
returnValue.insert(
make_pair(it->first, *get<2>(it->second))
);
}
return returnValue;
}
virtual bool advanceRangeIter(RangeIterMap &rangeIter) {
for (typename RangeIterMap::iterator it = rangeIter.begin(); ; ) {
++(get<2>(it->second));
if (get<2>(it->second) == get<1>(it->second)) {
if (it + 1 == rangeIter.end()) {
return mode::stopIter;
} else {
// cascade
get<2>(it->second) = get<0>(it->second);
++it;
}
} else {
// normal break point
return mode::continueIter;
}
}
return mode::continueIter;
}
};
typedef boost::integer_range<int> _intRange;
typedef boost::container::flat_map<char, _intRange> CharRange;
typedef boost::container::flat_map<char, int> ResidueCount;
template <class Container2D,
class return_type = boost::container::flat_map<typename Container2D::value_type::first_type,
typename Container2D::value_type::second_type::value_type> >
struct BaseIterContainer {
typedef CartProductIterator2DMap<Container2D, return_type> const_iterator;
const Container2D &_container;
BaseIterContainer( const Container2D &container) : _container(container) {}
const_iterator begin() const { return const_iterator(_container); }
const_iterator end() const { return const_iterator(); }
};
typedef BaseIterContainer<CharRange, ResidueCount> BaseCharRangeIter;
typedef CartProductIterator2DMap<CharRange, ResidueCount> BaseCPIterator;
class DerivedCPIterator : public BaseCPIterator {
public:
DerivedCPIterator() : BaseCPIterator() {}
DerivedCPIterator(const CharRange & charRange) : BaseCPIterator(charRange) {}
protected:
ResidueCount genReturnValue(const RangeIterMap &rangeIter) {
std::cout << "Calling derived class." << std::endl;
ResidueCount returnValue;
for( RangeIterMap::const_iterator it = rangeIter.begin();
it != rangeIter.end(); ++it) {
const char aa = it->first;
const int aaCount = *get<2>(it->second);
if (aaCount > 0) {
returnValue.insert(
make_pair(aa, aaCount)
);
}
}
return returnValue;
}
};
struct DerivedCharRangeIter {
typedef DerivedCPIterator const_iterator;
const CharRange &_container;
DerivedCharRangeIter( const CharRange &container) : _container(container) {}
const_iterator begin() const { return const_iterator(_container); }
const_iterator end() const { return const_iterator(); }
};
std::ostream& operator<<(std::ostream& out, const ResidueCount &rCount) {
foreach(const ResidueCount::value_type& aaCount, rCount) {
char aa = aaCount.first;
int totalAACount = aaCount.second;
out << "(" << aa << "," << totalAACount << ")";
}
return out;
}
int main(int argc, char **argv) {
cout << "Base Container" << endl;
CharRange test;
test.insert(make_pair('a', _intRange(0, 3)));
test.insert(make_pair('b', _intRange(0, 3)));
BaseCharRangeIter t(test);
BaseCharRangeIter::const_iterator it = t.begin();
for( ;it != t.end(); ++it) {
cout << *it << endl;
}
cout << endl;
cout << "Derived Container: " << endl;
DerivedCharRangeIter r(test);
DerivedCharRangeIter::const_iterator rt = r.begin();
for( ; rt != r.end(); ++rt) {
cout << *rt << endl;
}
return 0;
}
And the results I get:
Base Container
Calling base class.
(a,0)(b,0)
Calling base class.
(a,1)(b,0)
Calling base class.
(a,2)(b,0)
Calling base class.
(a,0)(b,1)
Calling base class.
(a,1)(b,1)
Calling base class.
(a,2)(b,1)
Calling base class.
(a,0)(b,2)
Calling base class.
(a,1)(b,2)
Calling base class.
(a,2)(b,2)
Derived Container:
Calling base class.
(a,0)(b,0)
Calling derived class.
(a,1)
Calling derived class.
(a,2)
Calling derived class.
(b,1)
Calling derived class.
(a,1)(b,1)
Calling derived class.
(a,2)(b,1)
Calling derived class.
(b,2)
Calling derived class.
(a,1)(b,2)
Calling derived class.
(a,2)(b,2)
Each genReturnValue print its class (either base or derived) every call. The base class functions as it should. However, the derived class does not. The first iteration calls the base class genReturnValue and the 0s aren't filtered out. However, further iterations do.
Since this is my first foray into templates and derived classes, I'm sure I'm missing something obvious, but for the life of me I can't figure it out. GCC 4.6.3 and Clang 3.0-6 provide the same output.
Halp!
Edit: Also, I'm relatively new at C++ programming. I'm open to critiques, style or otherwise,if you have any. Thanks!
It has, actually, nothing to do with pointers; but is, instead, a limitation of the virtual functions.
During construction and destruction virtual calls cannot be purely virtual because of the order of construction and destruction of base classes relative to their derived counterparts, so instead they are statically resolved.
That is, a call to virtualfunc in a constructor or destructor of Base is (somehow) resolved to Base::virtualfunc. If this is a pure virtual function, then Undefined Behavior ensues.
As such, the general guideline is:
Never call virtual functions from constructors or destructors.
Example:
struct Base {
Base() { call(); }
virtual call() { std::cout << "Base\n"; }
};
struct Derived: Base {
Derived(int i): _i(i);
virtual call() { std::cout << "Derived" << _i << "\n"; }
int _i;
};
int main() {
Derived d(1);
};
This will print Base, not Derived1 as you might expect; and there is a good reason for this: remember the construction order of things:
Derived() is called
It automatically calls Base()
It calls _i(i)
It enters the body of Derived(), which does nothing
Therefore, when Base() is called, _i has not been initialized yet, so a call to call would be foolish. Thankfully the Standard has seen fit to provide a good work-around here, even though it is, most of the time, not what you would first expect.
You're base class CartProductIterator2DMap has a constructor that calls a virtual function:
CartProductIterator2DMap(const Container2DMap &container) {
rangeIterSetup(container);
}
this virtual function eventually calls another virtual function: genReturnValue.
Now, when the base class constructor is executing, the derived class has not been constructed yet. So the call to genReturnValue from the base class constructor invokes CartProductIterator2DMap::genReturnValue. But subsequent calls (after the object is fully constructed) invokes: DerivedCPIterator::genReturnValue.
You need to make sure that your base class constructor does not invoke any virtual functions.