Does std::any_cast call destructor? How the cast works? - c++

#include <iostream>
#include <any>
using namespace std;
class c {
public:
c() :a{ 0 } { cout << "constructor\n"; }
c(int aa) :a{ aa } { cout << "Constructor\n"; }
~c() { cout << "destructor\n"; }
int get() { return a; }
private:
int a;
};
auto main()->int
{
any a{ 5 };
cout << any_cast<int>(a) << '\n';
a.emplace<c>(3);
cout << '!' << any_cast<c>(a).get() << '\n';
//des
cout << '\n';
a.emplace<c>(9);
cout << '!' << any_cast<c>(a).get() << '\n';
//des
}
destructor called after each any_cast.
and, below code makes run-time error.
I think the cause is any_cast(C)'s work pipeline is might be like
~C() then X(C) ERROR!!C doesn't exist
any_cast really work like that?
I add blow codes and make run-time error.
class X {
public:
X() :a{ 0 } { cout << "xonstructor\n"; }
X(c& aa) :a{ aa.get() } { cout << "Xonstructor\n"; }
~X() { cout << "Xdestructor\n"; }
int get() { return a; }
private:
int a;
};
auto main()->int
{
any a{ 5 };
cout << any_cast<int>(a) << '\n';
a.emplace<c>(3);
cout << '!' << any_cast<X>(a).get() << '\n';
//runtime error after '!'
cout << '\n';
a.emplace<c>(9);
cout << '!' << any_cast<X>(a).get() << '\n';
}

You are copying a c (or X) from the one within the std::any. That copy is destroyed at the end of the expression, after having been streamed out.
any_cast does not do any conversion. It throws if you ask it for a type different to the one it stores. When you have emplaced a c and asked for an X, it throws std::bad_any_cast, because X is not c.

Related

Static Cast to CRTP Interface [duplicate]

This question already has answers here:
What is object slicing?
(18 answers)
Closed 1 year ago.
I am building up a CRTP interface and noticed some undefined behavior. So, I built up some sample code to narrow down the problem.
#include <iostream>
template <typename T>
class Base {
public:
int a() const { return static_cast<T const&>(*this).a_IMPL(); }
int b() const { return static_cast<T const&>(*this).b_IMPL(); }
int c() const { return static_cast<T const&>(*this).c_IMPL(); }
};
class A : public Base<A> {
public:
A(int a, int b, int c) : _a(a), _b(b), _c(c) {}
int a_IMPL() const { return _a; }
int b_IMPL() const { return _b; }
int c_IMPL() const { return _c; }
private:
int _a;
int _b;
int _c;
};
template <typename T>
void foo(const T& v) {
std::cout << "foo()" << std::endl;
std::cout << "a() = " << static_cast<Base<T>>(v).a() << std::endl;
std::cout << "b() = " << static_cast<Base<T>>(v).b() << std::endl;
std::cout << "c() = " << static_cast<Base<T>>(v).c() << std::endl;
}
int main() {
A v(10, 20, 30);
std::cout << "a() = " << v.a() << std::endl;
std::cout << "b() = " << v.b() << std::endl;
std::cout << "c() = " << v.c() << std::endl;
foo(v);
return 0;
}
The output of this code is:
a() = 10
b() = 20
c() = 30
foo()
a() = 134217855
b() = 0
c() = -917692416
It appears that there is some problem when casting the child class, which implements the CRTP "interface", to the interface itself. This doesn't make sense to me because the class A plainly inherits from Base so, shouldn't I be able to cast an instance of A into Base?
Thanks!
You copy and slice when you cast to Base<T>.
Cast to a const Base<T>& instead:
std::cout << "a() = " << static_cast<const Base<T>&>(v).a() << std::endl;
std::cout << "b() = " << static_cast<const Base<T>&>(v).b() << std::endl;
std::cout << "c() = " << static_cast<const Base<T>&>(v).c() << std::endl;
It turns out I was casting incorrectly to a value rather than a reference
std::cout << "a() = " << static_cast<Base<T>>(v).a() << std::endl;
should become
std::cout << "a() = " << static_cast<const Base<T>&>(v).a() << std::endl;

Is calling member functions without object instantiation undefined behaviour?

I have the following code:
#include <iostream>
#include <string>
class BaseNode {
public:
BaseNode(std::string s) {
std::cout << "Called BaseNode(string)" << std::endl;
}
BaseNode() {
std::cout << "Called BaseNode()" << std::endl;
}
void count(int num) {
std::cout << "count() in BaseNode " << num << std::endl;
}
};
class MyNode : public BaseNode {
public:
MyNode() : BaseNode("test") {
std::cout << "Called MyNode()" << std::endl;
}
void count(int num) {
std::cout << "count() in MyNode " << num << std::endl;
}
};
int main(int argc, char * argv[]) {
MyNode *mn;
mn->count(6);
return 0;
}
To my surprise this compiles and prints "count() in MyNode 6". But should it work?
If I declare count as virtual in the base class
class BaseNode {
public:
BaseNode(std::string s) {
std::cout << "Called BaseNode(string)" << std::endl;
}
BaseNode() {
std::cout << "Called BaseNode()" << std::endl;
}
virtual void count(int num) {
std::cout << "count() in BaseNode " << num << std::endl;
}
};
I get "Segmentation Faul" on the count call. What is going on behind the scenes here?
MyNode *mn; creates a Wild Pointer, or a Dangling Pointer--that is, one that points to memory you don't own. So trying to dereference the pointer and fetch that memory is indeed Undefined Behavior.
What is going on behind the scenes here?
Since this is Undefined Behavior, we don't know. The results here are determined by whatever your compiler decided to do, which could very well include making "demons fly out of your nose."

Function compiling even though it doesn't accept integer [duplicate]

This question already has answers here:
What is a converting constructor in C++ ? What is it for?
(3 answers)
Closed 3 years ago.
I am confused how can we pass an integer when the parameter of a function only accept a class of type enemy ( void foo(const Enemy& inKlep ).
Yet when we pass to it an int (300) it compiles. Why is this?
#include <iostream>
using namespace std;
class Enemy {
public:
Enemy() { cout << "E ctor" << endl; }
Enemy(int i) { cout << "E ctor " << i << endl; }
Enemy(const Enemy& src) {cout << "E copy ctor"<< endl;}
Enemy& operator=(const Enemy& rhs) {cout<<"E="<<endl;}
virtual ~Enemy() { cout << "E dtor" << endl; }
void hornet(int i=7) const { // Not virtual!
cout << "E::hornet " << i << endl;
}
};
class Scott : public Enemy {
public:
Scott() : Enemy(1) { cout << "S ctor" << endl; }
Scott& operator=(const Scott& rhs) {cout<<"S="<<endl;}
virtual ~Scott() { cout << "S dtor" << endl; }
void hornet(int i=7) const {
cout<<"S::hornet " << i << endl;
}
};
void foo(const Enemy& inKlep) {
Enemy theEnemy;
inKlep.hornet(2);
}
int main(int argc, char** argv) {
foo(300);
cout << "Done!" << endl; // Don't forget me!
}
In C++, it is valid code for an input parameter to implicitly construct an object if the function expects an object that can be constructed from that parameter. So, for example:
struct CustomInt {
int val;
CustomInt() : CustomInt(0) {}
CustomInt(int value) : val(value) {}
};
void func(CustomInt obj) {
std::cout << obj.val << std::endl;
}
int main() {
func(5); //Valid; will print '5' to the console
}
If you don't want to allow this, you need to add the keyword explicit to the constructor to prevent this.
struct CustomInt {
int val;
CustomInt() : CustomInt(0) {}
explicit CustomInt(int value) : val(value) {}
};
void func(CustomInt obj) {
std::cout << obj.val << std::endl;
}
int main() {
//func(5); //Invalid; will cause a compile-time error
func(CustomInt(5)); //Valid; will print '5' to the console
}

VC++ polymorphic arrays

I found that such code
#include <iostream>
class A
{
public:
A()
{
std::cout << "cA" << std::endl;
}
virtual ~A()
{
std::cout << "dA" << std::endl;
}
char a[11];
};
class B : public A
{
public:
B()
{
std::cout << "cB" << std::endl;
}
~B()
{
std::cout << "dB" << std::endl;
}
char a[21];
};
int main()
{
{
A* aa = new B[5];
std::cout << "==============" << std::endl;
delete[] aa;
}
return 0;
}
works perfectly well in VC++ compiler, but fail when complied by GCC. I understand why using arrays like this could be bad idea (thanks Meyers) but how is it works in VC++? Is it store size of real object before array?

Explicity pass base type

I have an explicit function that takes a reference to the base type of a class. What is the proper way to pass that in?
I am currently doing a static cast:
#include <iostream>
using namespace std;
struct Base
{
Base() { cout << "Base Constructor" << endl; }
Base(Base const& c) { cout << "Base-Base Constructor" << endl; }
};
struct Derived : public Base
{
Derived() { cout << "Derived Constructor" << endl; }
explicit Derived(Base const& c) { cout << "Derived-Base Constructor" << endl; }
Derived(Derived const& c) { cout << "Derived-Derived Constructor" << endl; }
};
int main()
{
Base B;
cout << "\n";
Derived D;
cout << "\n";
Base* test1 = new Derived(D);
cout << "\n";
Base* test3 = new Derived(static_cast<Base>(D));
cout << "\n";
Base* test2 = new Derived(B);
cout << "\n";
return 0;
}
but that calls the copy constructor of the base class.
I could pass *static_cast<Base*>(&D), but that seems a bit hackish. I feel like I am just overlooking a simple way to do this. Thanks.
Use this:
static_cast<Base&>(D)
Or this:
static_cast<const Base&>(D)