This part of the question provides background information and can be ignored
I am working on a template library which heavily relies on the use of the curiously recurring template pattern. The idea behind the class structure is that the user can either
1). Use predefined classes with standard methods. These classes are very simple leafs of the base class that only provide constructors/destructor, declare the variable members and declare the base class(es) as friend(s). All methods that operate on the variable members of the derived classes are defined in the base class(es).
2). Use the base classes to create his/her own extensions. This method also allows users to introduce their own methods that operate on the same variable members.
Only a single level inheritance is enforced by design.
My question is, primarily, about the clause 2. In the current implementation the user has to define all constructors implicitly (i.e. describe full process of memory allocation for dynamic variable members of the class, etc).
Question
The example below demonstrates an investigation into a possibility to use the CRTP to provide the definition of the allocation of the memory of the heap variables of the derived classes in the base class constructors.
Part of the base class
template<class TLeafType, class MyClass> class sysBaseDiscreteTrajectoryPoint {
...
//one of the base constructors
sysBaseDiscreteTrajectoryPoint(const MyClass& MyClassInstance) {
std::cout << "Base additional constructor called" << std::endl;
std::cout << asLeaf().Point << std::endl;
asLeaf().Point=new MyClass(MyClassInstance);
std::cout << asLeaf().Point << std::endl;
}
TLeafType& asLeaf(void) {
return static_cast<TLeafType&>(*this);
}
...
};
The derived class:
template<class MyClass>
class sysDiscreteTrajectoryPoint: public sysBaseDiscreteTrajectoryPoint<sysDiscreteTrajectoryPoint<MyClass>, MyClass> {
...
friend class sysBaseDiscreteTrajectoryPoint<sysDiscreteTrajectoryPoint<MyClass>, MyClass>;
private:
MyClass* Point;
public:
sysDiscreteTrajectoryPoint(const MyClass& MyClassInstance): sysBaseDiscreteTrajectoryPoint<sysDiscreteTrajectoryPoint<MyClass>, MyClass>(MyClassInstance){
std::cout << "Derived additional constructor called " << std::endl;
std::cout << Point << std::endl;
std::cout << *Point << std::endl;
}
...
}
main:
int a(5);
sysDiscreteTrajectoryPoint<int> A(a);
The code produces the following output:
Base additional constructor called
0x847ff4
0x8737008
Derived additional constructor called
0x8737008
5
Derived destructor called
Base destructor called
The output suggests that the concept may be feasible. However, I have two questions.
1). I would like to ensure that I understand all processes that happen during the execution of the code. In particular, I am interested in the efficiency of the process, as I may need to instantiate a substantial amount of objects from the classes presented above and I would like to understand what happens with Point
(are there any hidden redefinitions?)
2). The question is related to the use of the library boost
for the definition of smart pointers for the members of the derived class. When I tried replacing the raw pointer with boost::shared_ptr
, I received a segmentation fault error when trying to allocate memory for the member of the derived class through the base class. The important sections of the code are shown below.
Part of the base class:
template<class TLeafType, class MyClass> class sysBaseDiscreteTrajectoryPoint {
...
//one of the base constructors
sysBaseDiscreteTrajectoryPoint(const MyClass& MyClassInstance) {
std::cout << "Base additional constructor called" << std::endl;
std::cout << asLeaf().Point << std::endl;
asLeaf().Point.reset(new MyClass(MyClassInstance));
std::cout << asLeaf().Point << std::endl;
}
TLeafType& asLeaf(void) {
return static_cast<TLeafType&>(*this);
}
...
};
Part of the derived class:
template<class MyClass>
class sysDiscreteTrajectoryPoint: public sysBaseDiscreteTrajectoryPoint<sysDiscreteTrajectoryPoint<MyClass>, MyClass> {
...
friend class sysBaseDiscreteTrajectoryPoint<sysDiscreteTrajectoryPoint<MyClass>, MyClass>;
private:
boost::shared_ptr<MyClass> Point;
public:
sysDiscreteTrajectoryPoint(const MyClass& MyClassInstance): sysBaseDiscreteTrajectoryPoint<sysDiscreteTrajectoryPoint<MyClass>, MyClass>(MyClassInstance){
std::cout << "Derived additional constructor called " << std::endl;
std::cout << Point << std::endl;
std::cout << *Point << std::endl;
}
...
}
main:
int a(5);
sysDiscreteTrajectoryPoint<int> A(a);
The code produces the following output:
Base additional constructor called
0x28d324
Segmentation fault
I have also tried scoped_ptr
. However, it failed at run time but with a different error:
Base additional constructor called
*** glibc detected *** ./TestSystem: free(): invalid pointer: 0x00d3fff4 ***
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(+0x6b961)[0xc4e961]
...
I assume that it is related to the specifics of the operation of boost smart pointers. Does anyone know how to resolve this issue?