I want to destroy the templated object, but keep the allocated memory to be filled. Unfortunately, the destructor of the object is never called, and stepping through the code, it skips the manual call.
#include <iostream>
template <typename type> class TestClass
{
private:
type *data;
public:
TestClass();
~TestClass();
template <typename T> void Set(T &&element);
void Replace();
};
template <typename type> TestClass<type>::TestClass()
{
data = reinterpret_cast<type *>(new char[sizeof(type)]);;
}
template <typename type> TestClass<type>::~TestClass()
{
}
template <typename type> template <typename T> void TestClass<type>::Set(T &&element)
{
new(data) type(static_cast<T &&>(element));
}
template <typename type> void TestClass<type>::Replace()
{
type *pointer = reinterpret_cast<type *>(&data[0]);
pointer->~type();
//Fill with data
}
class MyClass
{
public:
MyClass()
{
}
~MyClass()
{
std::cout << "Called" << "\n";
}
};
int main()
{
MyClass *myClass = new MyClass();
TestClass<MyClass *> myObject;
myObject.Set(myClass);
myObject.Replace();
return 0;
}
I have tested this in VS 2017 and on an online C++ compiler. Both skip the pointer->~type(); when stepping through and the destructor is never called.
Edit: Rewrote code which now reproduces the error.
It does call destructor.
#include <iostream>
class Type
{
public:
~Type()
{
std::cout<< __FUNCTION__ << "\n";
}
};
template <typename type> class MyClass
{
private:
type *data;
public:
MyClass();
~MyClass(){}
void Replace();
};
template <typename type> MyClass<type>::MyClass()
{
data = reinterpret_cast<type *>(new char[sizeof(type)]);;
}
template <typename type> void MyClass<type>::Replace()
{
type *pointer = &data[0];
pointer->~type();
//Fill with replacement data
}
int main()
{
MyClass<Type> myClass;
std::cout <<"Before destruction\n";
myClass.Replace();
std::cout << "After destruction\n";
return 0;
}
To allow templates to deal generally with types, C++ allows a obj.~type() or ptr->~type() syntax even when the type is not a class type (but not for an array type). The meaning is the same as whatever would happen to an automatic object of that type at the end of its scope: if it is a class type, the destructor is called, and if not, nothing happens. For the case when the type is not a class type, this syntax is called a pseudo-destructor.
Now looking at your example, you're using the class template specialization TestClass<MyClass*>. So in the instantiation of the member definition for TestClass<type>::Replace(), type is an alias for MyClass*. The statement
type *pointer = reinterpret_cast<type *>(&data[0]);
defines a variable of type type*, which is MyClass**. (The right-hand side is confusing: &data[0] is the same as data assuming it points at something, and both expressions already have type type*.)
The statement
pointer->~type();
says to destroy the object of type type which pointer points at. That is, it says to destroy the object of type MyClass* which is *pointer. MyClass* is not a class type; it is a pointer type. So this is a call to a pseudo-destructor, and absolutely nothing happens.
There's not enough context to say for certain how this would be fixed, but perhaps you need to use TestClass<MyClass> instead of TestClass<MyClass*>? (Also, in real code don't forget the Rule Of Five/Rule Of Three.)
Related
I have two class templates that must be templates (C++). I just simplified their code to show the essence of the problem. How to pass an object (obj1) from one template (MyClass1) to another object (obj2) from second template (MyClass2)? I tried through the template parameter and the constructor, but I still have compilation errors. How to do it correctly? What is important, I don't know template parameters, therefore solution has be universal, not for specified parameters. Object should be passed by pointer or reference, I don't need its copy.
template<int a, int b>
class MyClass1 {
public:
MyClass1() {
// Do something...
}
int foo(int x) {
return a * x + b;
}
};
template<double m, double n>
class MyClass2 {
public:
MyClass2() {
// Do something
}
double bar(int x) {
// Do something with x using object of MyClass1 and then with m...
}
double zet(int x) {
// Do something with x using object of MyClass1 and then with n...
}
};
int main() {
MyClass1<4, 3> obj1;
MyClass2<3.14, 2.56> obj2; // <-- How to pass obj1 here???
// Maybe that way?: MyClass2<3.14, 2.56, obj1> obj2;
// Or that way?: MyClass2<3.14, 2.56> obj2(obj1);
obj1.foo(12);
obj2.bar(1.234);
obj2.zet(5.678);
}
I'm not sure if this is relevant to this problem, but I'm writing C++ code for AVR in Atmel Studio 7 with standard settings.
Your code does not compile with C++11 because of this:
A non-type template parameter must have a structural type, which is
one of the following types (optionally cv-qualified, the qualifiers
are ignored):
lvalue reference type (to object or to function);
an integral type;
a
pointer type (to object or to function);
a pointer to member type (to
member object or to member function);
an enumeration type;
std::nullptr_t; (since C++11)
a floating-point type; (since C++20)
Regarding your core problem, you can do the something like this:
template<int m, int n, typename Obj1Type>
class MyClass2 {
Obj1Type obj1_;
public:
MyClass2() {
// Do something
}
MyClass2(Obj1Type const& obj1) {
obj1_ = obj1;
}
// ...
};
And then in main:
int main() {
MyClass1<4, 3> obj1;
MyClass2<3, 2, MyClass1<4, 3>> obj2(obj1);
obj1.foo(12);
obj2.bar(1);
obj2.zet(5);
}
Check it out live
UPDATE
You could also make use of inheritance and create a simple base class for this purpose:
class BaseMyClass1 {};
template<int a, int b>
class MyClass1 : public BaseMyClass1 {
// ...
};
template<int m, int n>
class MyClass2 {
BaseMyClass1 obj1_;
public:
MyClass2() {
// Do something
}
template <typename Obj1Type>
MyClass2(Obj1Type const& obj1) {
obj1_ = obj1;
}
// ...
};
And then in main:
int main() {
MyClass1<4, 3> obj1;
MyClass2<3, 2> obj2(obj1);
obj1.foo(12);
obj2.bar(1);
obj2.zet(5);
}
This saves you declaring a template in template parameter list. However, this might not be the perfect solution for you because it introduces object slicing.
Check it out live
Template class accepts another template class as template parameter. So you can pass typename T for Myclass2.
Example program:
You can try something like this:
#include <iostream>
using namespace std;
template<typename T1>
class Myclass1
{
public:
Myclass1(T1 x):m1_x(x)
{
cout << "Myclass1 C'tor" << m1_x << endl;
}
T1 m1_x;
T1 get_x()
{
return m1_x;
}
};
template < typename T1 >
class Myclass2
{
public:
Myclass2(T1 x): m_x(x)
{
cout << "My class 2 C'tor with value" << m_x.get_x() << endl;
}
public:
T1 m_x;
};
int main()
{
Myclass1 <int > obj1(5000);
Myclass2< Myclass1 <int> > obj2 ( obj1 );
return 0;
}
I was reading the sample code on another post Specializations only for C++ template function with enum non-type template parameter
and I'm trying to take it one step further, by using a overloaded conversion operator to use the object as if it was its enum member to call a template function.
//in my .h
enum class AllowedTypes { Cat, Dog };
class A {
AllowedTypes animal;
public:
//constructor
A(AllowedTypes t): animal(t) {};
explicit operator AllowedTypes*() const { return (AllowedTypes*) animal; }
operator AllowedTypes() const { return animal; }
template <AllowedTypes type>
void ability() const;
}
//second class
struct B{
//tempalte function
template <AllowedTypes type>
void ability() const;
}
//in my cpp
template<>
void B::ability<AllowedTypes::Dog>() const
{
std::cout << "Dog ability." << std::endl;
}
template<>
void B::ability<AllowedTypes::Cat>() const
{
std::cout << "Cat ability." << std::endl;
}
//in my main
Class* a = new A(AllowedType(1))
Class* b = new B();
//this calls work!
b->ability<AllowedTypes::Cat>();
//trying to get the type and calling ability via conversion doesn't
AllowedTypes type = (AllowedTypes)*a; // this converts correctly!
b->ability<type>(); //does not call correctly
this last line doesn't work, I'm trying to put my converted object in the template and call the ability specific to the type that A has. I've tried a few different things but can't seem to find what I'm looking for, is there a proper way to do this?
The problem in your code is that you are trying to set a template type parameter using a runtime value rather than compile time value.
Class* a = new A(AllowedType(1)) // The call to new here makes 'type' below a runtime value
b->ability<AllowedTypes::Cat>(); // AllowedTypes::Cat can be supplied at compile time
AllowedTypes type = (AllowedTypes)*a; // this converts correctly!
b->ability<type>(); //does not call correctly
Here is your code running online which points to the exact problem. Next time your confused about why your template type isnt getting deduced correctly/throwing an error use constexpr to figure out why.
And here is an answer explaining why new results in an ill-formed constexpr: C++14: can you call new in a constexpr?
I have the following code: (live on Coliru)
#include <iostream>
class ClassA{
public:
ClassA(int i) : m_int(i){};
int m_int;
};
class Master{
public:
Master(){};
~Master(){
delete m_classMain;
}
ClassA* m_classMain;
template<typename T>
void mem(T* t, int i){
t = new T(i);
}
void test() {
mem(m_classMain,3);
}
int get_i() const{
return m_classMain->m_int;
}
};
int main()
{
Master* master = new Master();
master->test();
std::cout << master->get_i() << std::endl;
delete master;
}
I would like to initialize the object ClassA* m_classMain through the method mem(T* t, int i) which is a template method.
For some reason I only get a segmentation fault. I think t = new T(i) might be the problem here, but I can not figure why (unfortunately I do not have a debugger at hand).
In your posted code, the member variable m_classMain is not initialized. Calling delete on it is cause for undefined behavior.
The call
mem(m_classMain,3);
does not initialize m_classMain since you are passing it by value. To initialize it in mem, you'll have to pass it by reference.
template<typename T>
void mem(T*& t, int i){ //T*& t, not T* t.
t = new T(i);
}
As a matter of good coding practice, make sure that all member variables are initialized in the constructor(s).
Master() : m_classMain(nullptr) {};
You are passing the t parameter of the mem() function by value. It gets destroyed on function exit. Consider passing by reference, or accessing the member directly from the member function.
In designing a DSL (which compiles into C++), I found it convenient to define a wrapper class that, uppon destruction, would call a .free() method on the contained class:
template<class T>
class freeOnDestroy : public T {
using T::T;
public:
operator T&() const { return *this; }
~freeOnDestroy() { T::free(); }
};
The wrapper is designed to be completely transparent: All methods, overloads and constructors are inherited from T (at least to my knowledge), but when included in the wrapper, the free() method is called uppon destruction. Note that I explicitly avoid using T's destructor for this since T::free() and ~T() may have different semantics!
All this works fine, untill a wrapped class gets used as a member to a non-reference templated call, at which point freeOnDestroy is instantiated, calling free on the wrapped object. What I would like to happen is for the tempated method to use T instead of freeOnDestroy<T>, and to implicitly cast the parameter into the supperclass. The following code sample illustrates this problem:
// First class that has a free (and will be used in foo)
class C{
int * arr;
public:
C(int size){
arr = new int[size];
for (int i = 0; i < size; i++) arr[i] = i;
}
int operator[] (int idx) { return arr[idx]; }
void free(){ cout << "free called!\n"; delete []arr; }
};
// Second class that has a free (and is also used in foo)
class V{
int cval;
public:
V(int cval) : cval(cval) {}
int operator[] (int idx) { return cval; }
void free(){}
};
// Foo: in this case, accepts anything with operator[int]
// Foo cannot be assumed to be written as T &in!
// Foo in actuality may have many differently-templated parameters, not just one
template<typename T>
void foo(T in){
for(int i = 0; i < 5; i++) cout << in[i] << ' ';
cout << '\n';
}
int main(void){
C c(15);
V v(1);
freeOnDestroy<C> f_c(15);
foo(c); // OK!
foo(v); // OK!
foo<C>(f_c); // OK, but the base (C) of f_c may not be explicitly known at the call site, for example, if f_c is itself received as a template
foo(f_c); // BAD: Creates a new freeOnDestroy<C> by implicit copy constructor, and uppon completion calls C::free, deleting arr! Would prefer it call foo<C>
foo(f_c); // OH NO! Tries to print arr, but it has been deleted by previous call! Segmentation fault :(
return 0;
}
A few non solutions I should mention are:
Making freeOnDestroy::freeOnDestroy(const freeOnDestroy &src) explicit and private, but this seems to override T's constructor. I'd hoped it would try to implicitly convert it to T and use that as the template argument.
Assume foo receives a reference of its templated arguments (as in void foo(T &in): This is neither the case, nor desirable in some cases
Always explicitly template the call to foo, as in foo<C>(f_c): f_c itself may be templated, so it's hard to know to instantiate foo with C (yes, this could be done with creating multiple versions of foo, to remove the wrappers one by one, but I can't find a way of doing that without creating a different overload for each templated argument of foo).
In summary, my question is: Is there a clean(ish) method to ensure a base class will be casted to its superclass when resolving a template? Or, if not, is there some way of using SFINAE, by causing a substitution failure when the template argument is an instance of the wrapper class, and thus force it to use the implicit cast to the wrapped class (without duplicating each foo-like method signature possibly dozens of times)?
I presently have a work-arround that involves changes in the DSL, but I'm not entirely happy with it, and was curious if it was at all possible to design a wrapper class that works as described.
The problem here not when "wrapped class gets used as a member to a non-reference templated call".
The problem here is that the template wrapper -- and likely its superclass too -- has violated the Rule Of Three.
Passing an instance of the class as a non-reference parameter is just another way of saying "passing by value". Passing by value makes a copy of the instance of the class. Neither your template class -- nor its wrapped class, most likely -- has an explicit copy constructor; as such the copied instance of the class has no knowledge that it is a copy, hence the destructor does what it thinks it should do.
The correct solution here is not to hack something up that makes passing an instance of freeOnDestroy<T> by value end up copying T, rather than freeOnDestroy<T>. The correct solution is to add a proper copy-constructor and the assignment operator to both the freeOnDestroy template, and possibly any superclass that uses it, so that everything complies with the Rule Of Three.
You can use a properly defined detector and a sfinaed function, as it follows:
#include<iostream>
#include<type_traits>
template<class T>
class freeOnDestroy : public T {
using T::T;
public:
operator T&() const { return *this; }
~freeOnDestroy() { T::free(); }
};
template<typename T>
struct FreeOnDestroyDetector: std::false_type { };
template<typename T>
struct FreeOnDestroyDetector<freeOnDestroy<T>>: std::true_type { };
class C{
int * arr;
public:
C(int size){
arr = new int[size];
for (int i = 0; i < size; i++) arr[i] = i;
}
int operator[] (int idx) { return arr[idx]; }
void free(){ std::cout << "free called!\n"; delete []arr; }
};
class V{
int cval;
public:
V(int cval) : cval(cval) {}
int operator[] (int idx) { return cval; }
void free(){}
};
template<typename..., typename T>
std::enable_if_t<not FreeOnDestroyDetector<std::decay_t<T>>::value>
foo(T in) {
std::cout << "here you have not a freeOnDestroy based class" << std::endl;
}
template<typename..., typename T>
std::enable_if_t<FreeOnDestroyDetector<std::decay_t<T>>::value>
foo(T &in) {
std::cout << "here you have a freeOnDestroy based class" << std::endl;
}
int main(void){
C c(15);
V v(1);
freeOnDestroy<C> f_c(15);
foo(c);
foo(v);
foo<C>(f_c);
foo(f_c);
foo(f_c);
return 0;
}
As you can see by running the example, free is called only once, that is for the freeOnDestroy created in the main function.
If you want to forbid definitely freeOnDestroy as a parameter, you can use a single function as the following one:
template<typename..., typename T>
void foo(T &in) {
static_assert(not FreeOnDestroyDetector<std::decay_t<T>>::value, "!");
std::cout << "here you have a freeOnDestroy based class" << std::endl;
}
Note that I added a variadic parameter as a guard, so that one can no longer use foo<C>(f_c); to force a type to be used.
Remove it if you want to allow such an expression. It was not clear from the question.
One solution, which, although a little ugly, seems to work, is to use an overloaded unwrapping method, such as:
template<typename T> T freeOnDestroyUnwrapper(const T &in){ return in; }
template<typename T> T freeOnDestroyUnwrapper(const freeOnDestroy<T> &in){ return in; }
template<typename T> T freeOnDestroyUnwrapper(const freeOnDestroy<typename std::decay<T>::type> &in){ return in; }
template<typename T> T& freeOnDestroyUnwrapper(T &in){ return in; }
template<typename T> T& freeOnDestroyUnwrapper(freeOnDestroy<T> &in){ return in; }
template<typename T> T& freeOnDestroyUnwrapper(freeOnDestroy<typename std::decay<T>::type> &in){ return in; }
Then, calls can be made using the unwrapper:
int main(void){
C c(15);
V v(1);
freeOnDestroy<C> f_c(15);
foo(freeOnDestroyUnwrapper(c));
foo(freeOnDestroyUnwrapper(v));
foo<C>(freeOnDestroyUnwrapper(f_c));
foo(freeOnDestroyUnwrapper(f_c));
foo(freeOnDestroyUnwrapper(f_c));
return 0;
}
Or, to make this less verbose, we can alter foo so it does this for us:
template<typename T>
void _foo(T in){
for(int i = 0; i < 5; i++) cout << in[i] << ' ';
cout << '\n';
}
template<typename... Ts>
void foo(Ts&&... args){
_foo(freeOnDestroyUnwrapper(args)...);
}
And then call it as normal:
int main(void){
C c(15);
V v(1);
freeOnDestroy<C> f_c(15);
foo(c);
foo(v);
//foo<C>(f_c); // This now doesn't work!
foo(f_c);
foo(f_c);
return 0;
}
This seems to work for any number of arguments foo may have (of different templates, if needed), and seems to behave appropriately when foos input is a reference (which does not occur in my context, but would be good for the sake of making this solution generic).
I'm not convinced that this is the best solution, or that it generalizes to every case, plus, having to double all declarations is a bit cumbersome, and opaque to most IDEs autocomplete features. Better solutions and improvements are welcome!
How does one use inheritance when we have a template class have template pointer
We know that base class pointer can easily point to a derived class object . I created another template class and passed base and derived in it . However even with an overloaded = operator i cant make then equal which is my need .
Please take a look at my sample code as it explains clearly the situation.
#include <iostream>
using namespace std;
class base1
{
public:
int a;
virtual int reset(){
a=0;
return a;
}
};
class derived1: public base1
{
public:
int b;
int reset(){
b=0;
return b;
}
};
template <class T>
class templateClass{
public:
T *P;
T& operator = (templateClass &b )
{
this.p = reinterpret_cast<T>(b.p);
return *this;
}
void resetMyself(){
P->reset();
}
};
int main() {
// your code goes here
templateClass<base1> *p = new templateClass<base1> () ;
templateClass<derived1> *q = new templateClass<derived1>() ;
p=q;
p->resetMyself();
return 0;
}
When i compile my code i get
prog.cpp: In function ‘int main()’:
prog.cpp:44:3: error: cannot convert ‘templateClass<derived1>*’ to ‘templateClass<base1>*’ in assignment
p=q;
^
templateClass<derived1> and templateClass<base1> are as different as int and double. You can't assign a pointer to one to a pointer to the other.
You can, however, make templateClass<derived1> assignable to templateClass<base1> with a custom templated assignment operator:
template <class T>
class templateClass{
public:
T *P;
template <class U>
templateClass& operator = (const templateClass<U> &b )
{
P = b.P;
return *this;
}
void resetMyself(){
P->reset();
}
};
Then you can do something like (demo):
templateClass<base1> p;
templateClass<derived1> q;
p = q;
Note that your original assignment operator's signature is incorrect. Also, reinterpret_cast is a terrible idea for this. To perform a pointer-to-base to pointer-to-derived conversion, use static_cast. The above version uses no cast and so allows implicit conversions only (i.e., from derived to base but not the other way around).