J
John Harrison
Rather a long program I'm afraid but I don't think I can cut it down any
further.
What I'm trying to do is construct a complex object Y from several X objects
in a complex expression. I'm trying to do this without creating any
temporaries of Y. To do that I'm defined a number of proxy classes which
contain references to the arguments in the expression. All the proxies
define a conversion operator to Y which will ultimately be used to create
the Y object. The issue for me is whether I'm guaranteed that all the
temporaries will still exist when the conversion happens. Here's the code
#include <iostream>
using namespace std;
int gen = 0;
class X
{
};
class Y
{
};
class Proxy
{
public:
Proxy() : id(gen++) {}
Proxy(const Proxy&) : id(gen++) {}
virtual ~Proxy() {}
operator Y()
{
cout << "convert\n";
return Y();
}
protected:
int id;
};
class XX_proxy : public Proxy
{
public:
XX_proxy(const X& l, const X& r) : left(l), right(r) { cout << "XX" << id
<< '\n'; }
~XX_proxy() { cout << "~XX" << id << '\n'; }
private:
const X& left;
const X& right;
};
class AX_proxy : public Proxy
{
public:
AX_proxy(const Proxy& l, const X& r) : left(l), right(r) { cout << "AX" <<
id << '\n'; }
~AX_proxy() { cout << "~AX" << id << '\n'; }
private:
const Proxy& left;
const X& right;
};
class XA_proxy : public Proxy
{
public:
XA_proxy(const X& l, const Proxy& r) : left(l), right(r) { cout << "XA" <<
id << '\n'; }
~XA_proxy() { cout << "~XA" << id << '\n'; }
private:
const X& left;
const Proxy& right;
};
class AA_proxy : public Proxy
{
public:
AA_proxy(const Proxy& l, const Proxy& r) : left(l), right(r) { cout << "AA"
<< id << '\n'; }
~AA_proxy() { cout << "~AA" << id << '\n'; }
private:
const Proxy& left;
const Proxy& right;
};
XX_proxy operator|(const X& l, const X& r)
{
return XX_proxy(l, r);
}
AX_proxy operator|(const Proxy& l, const X& r)
{
return AX_proxy(l, r);
}
XA_proxy operator|(const X& l, const Proxy& r)
{
return XA_proxy(l, r);
}
AA_proxy operator|(const Proxy& l, const Proxy& r)
{
return AA_proxy(l, r);
}
int main()
{
X x1, x2, x3, x4;
Y y = x1 | x2 | x3 | x4;
}
The following program outputs
XX0
AX1
AX2
convert
~AX2
~AX1
~XX0
on the two compilers I've tested it on, which is good, "convert" is output
before any of the destructors are called. But I'm not sure if this is
guaranteed behaviour. I've tried reading the standard but its a bit opaque
to me.
Thanks,
John
further.
What I'm trying to do is construct a complex object Y from several X objects
in a complex expression. I'm trying to do this without creating any
temporaries of Y. To do that I'm defined a number of proxy classes which
contain references to the arguments in the expression. All the proxies
define a conversion operator to Y which will ultimately be used to create
the Y object. The issue for me is whether I'm guaranteed that all the
temporaries will still exist when the conversion happens. Here's the code
#include <iostream>
using namespace std;
int gen = 0;
class X
{
};
class Y
{
};
class Proxy
{
public:
Proxy() : id(gen++) {}
Proxy(const Proxy&) : id(gen++) {}
virtual ~Proxy() {}
operator Y()
{
cout << "convert\n";
return Y();
}
protected:
int id;
};
class XX_proxy : public Proxy
{
public:
XX_proxy(const X& l, const X& r) : left(l), right(r) { cout << "XX" << id
<< '\n'; }
~XX_proxy() { cout << "~XX" << id << '\n'; }
private:
const X& left;
const X& right;
};
class AX_proxy : public Proxy
{
public:
AX_proxy(const Proxy& l, const X& r) : left(l), right(r) { cout << "AX" <<
id << '\n'; }
~AX_proxy() { cout << "~AX" << id << '\n'; }
private:
const Proxy& left;
const X& right;
};
class XA_proxy : public Proxy
{
public:
XA_proxy(const X& l, const Proxy& r) : left(l), right(r) { cout << "XA" <<
id << '\n'; }
~XA_proxy() { cout << "~XA" << id << '\n'; }
private:
const X& left;
const Proxy& right;
};
class AA_proxy : public Proxy
{
public:
AA_proxy(const Proxy& l, const Proxy& r) : left(l), right(r) { cout << "AA"
<< id << '\n'; }
~AA_proxy() { cout << "~AA" << id << '\n'; }
private:
const Proxy& left;
const Proxy& right;
};
XX_proxy operator|(const X& l, const X& r)
{
return XX_proxy(l, r);
}
AX_proxy operator|(const Proxy& l, const X& r)
{
return AX_proxy(l, r);
}
XA_proxy operator|(const X& l, const Proxy& r)
{
return XA_proxy(l, r);
}
AA_proxy operator|(const Proxy& l, const Proxy& r)
{
return AA_proxy(l, r);
}
int main()
{
X x1, x2, x3, x4;
Y y = x1 | x2 | x3 | x4;
}
The following program outputs
XX0
AX1
AX2
convert
~AX2
~AX1
~XX0
on the two compilers I've tested it on, which is good, "convert" is output
before any of the destructors are called. But I'm not sure if this is
guaranteed behaviour. I've tried reading the standard but its a bit opaque
to me.
Thanks,
John