Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > problem with std::forward_as_tuple in MIL

Reply
Thread Tools

problem with std::forward_as_tuple in MIL

 
 
Frank Bergemann
Guest
Posts: n/a
 
      11-20-2011
Hi,
i have problems to create and forward tuple in MIL (member
initialization list).
Here's the program:
------------------------------- snip
--------------------------------------------------
#include <iostream>
#include <tuple>

template <typename T>
struct Elem
{
const T & _data;
Elem(const T & inp)
:_data(inp)
{ };

Elem(const Elem &)
{
std::cout << "!!! Elem copy c'tor invoked !!!" << std::endl;
};
};

template <typename T>
std:stream &
operator<<(
std:stream & out,
const Elem<T> & arg)
{
out << "Elem<T>(" << arg._data << ")";
return out;
}

/* Host class to actually hold tuple<> */
template <typename ...Types>
struct HostClassImpl
{
typedef typename std::tuple<Elem<Types>&&...> Type;

const Type _data;

HostClassImpl(Type && data)
: _data(data)
{ };

HostClassImpl(const HostClassImpl &)
{
std::cout << "HostClassImpl copy c'tor!" << std::endl;
};

HostClassImpl & operator=(const HostClassImpl &)
{
std::cout << "HostClassImpl assignment operator!" << std::endl;
return *this;
};
};

/*
* Host class front-end supporting variadic arguments
* just to enable the user level to do without std::forward_as_tuple()
* So HostClass actually shall do the std::forward_as_tuple() for the
user.
*/
template <typename ...Types>
struct HostClass
{
HostClassImpl<Types...> _impl;

template <typename ...Args>
HostClass(
Args&& ... args)
: _impl(std::forward_as_tuple(args...))
{ };

HostClass(const HostClass &)
{
std::cout << "HostClass copy c'tor!" << std::endl;
};

HostClass & operator=(const HostClass &)
{
std::cout << "HostClass assignment operator!" << std::endl;
return *this;
};
};

struct DummyHostClass
{
HostClassImpl<int, int, int> _impl;

DummyHostClass(void)
: _impl(std::forward_as_tuple(Elem<int>(10), Elem<int>(11),
Elem<int>(12)))
{
log();
};

void log(void)
{
std::cout << "DummyHostClass log data:" << std::endl;
std::cout << std::get<0>(_impl._data) << std::endl;
std::cout << std::get<1>(_impl._data) << std::endl;
std::cout << std::get<2>(_impl._data) << std::endl;
}

~DummyHostClass()
{
std::cout << "DummyHostClass d'tor" << std::endl;
};
};

int
main(
int argc,
char ** argv)
{

std::cout << std::endl << "Test (1): use Elem<int> only:" <<
std::endl;
Elem<int> elem(5);
std::cout << elem << std::endl;

std::cout << std::endl << "Test (2): create tuple<Elem<int>&&> - one
element only:" << std::endl;
std::tuple<Elem<int>&&> tuple(std::forward_as_tuple(Elem<int>(3)));
std::cout << std::get<0>(tuple) << std::endl;

std::cout << std::endl << "Test (3): create tuple<Elem<int>&&>,
Elem<int>&&> - two elements:" << std::endl;
std::tuple<Elem<int>&&, Elem<int>&&>
tuple2(std::forward_as_tuple(Elem<int>(5), Elem<int>(7)));
std::cout << std::get<0>(tuple2) << std::endl;
std::cout << std::get<1>(tuple2) << std::endl;

std::cout << std::endl << "Test (4): use HostClassImpl::Type
defnition for tuple<Elem<int>&&, Elem<int>&&> - two elements:" <<
std::endl;
HostClassImpl<int,int>::Type
tuple3(std::forward_as_tuple(Elem<int>(, Elem<int>(9)));
std::cout << std::get<0>(tuple3) << std::endl;
std::cout << std::get<1>(tuple3) << std::endl;

std::cout << std::endl << "Test (5): use HostClassImpl c'tor passing
already constructed tuple:" << std::endl;
HostClassImpl<int, int> hostImpl(std::forward_as_tuple(Elem<int>(10),
Elem<int>(11)));
std::cout << std::get<0>(hostImpl._data) << std::endl;
std::cout << std::get<1>(hostImpl._data) << std::endl;

std::cout << std::endl << "Test (6): use DummyHostClass with fixed
HostClassImpl within:" << std::endl;
DummyHostClass dummy;
dummy.log();

#if 0
std::cout << std::endl << "Test (7): use HostClass c'tor passing
individual tuple element (variadic template):" << std::endl;
HostClass<int, int> host(Elem<int>(12), Elem<int>(13));
std::cout << std::get<0>(host._impl._data) << std::endl;
std::cout << std::get<1>(host._impl._data) << std::endl;
#endif

return 0;
}
------------------------------- snap
--------------------------------------------------

Here's the output:

------------------------------- snip
--------------------------------------------------
> ./main


Test (1): use Elem<int> only:
Elem<T>(5)

Test (2): create tuple<Elem<int>&&> - one element only:
Elem<T>(3)

Test (3): create tuple<Elem<int>&&>, Elem<int>&&> - two elements:
Elem<T>(5)
Elem<T>(7)

Test (4): use HostClassImpl::Type defnition for tuple<Elem<int>&&,
Elem<int>&&> - two elements:
Elem<T>(
Elem<T>(9)

Test (5): use HostClassImpl c'tor passing already constructed tuple:
Elem<T>(10)
Elem<T>(11)

Test (6): use DummyHostClass with fixed HostClassImpl within:
DummyHostClass log data:
Elem<T>(10)
Elem<T>(11)
Elem<T>(12)
DummyHostClass log data:
Elem<T>(10)
Elem<T>(11871724)
Elem<T>(-1079275032)
DummyHostClass d'tor

------------------------------- snap
--------------------------------------------------

Why it the data away after leaving the constructor of DummyHostClass?
(Btw: 'DummyHostClass' is just a step towards intented 'HostClass' to
localize the problem.)

- many thanks!

best regards,
Frank
 
Reply With Quote
 
 
 
 
SG
Guest
Posts: n/a
 
      11-21-2011
On Nov 20, 3:28*pm, Frank Bergemann wrote:
> [...]
> Why it the data away after leaving the constructor of DummyHostClass?
> (Btw: 'DummyHostClass' is just a step towards intented 'HostClass' to
> localize the problem.)


I just skimmed Elem<> and HostClassImpl<> and stopped right there.
What is the point of all this? What are you actually trying to achieve
here? What is the point of Elem? It just wraps a reference. What is
the point of HostClassImpl? It just wraps a tuple of rvalue references
to Elem objects which itself wrap lvalue references. Surely this is
not what you want. That much I can tell you...

The first couple of lines of main already invoke undefined behaviour:

1 cout << "\nTest (1): use Elem<int> only:" << endl;
2 Elem<int> elem(5);
3 cout << elem << endl;

During execution of line 2 a temporary int object will be created and
initialized with 5 and it will be destroyed immeadately when execution
reaches the semicolon. Since Elem is defined like this:

template <typename T>
struct Elem
{
const T & _data;
Elem(const T & inp)
:_data(inp) {}
};

the object called 'elem' will store a dangling reference to an int-
object that does not exist anymore beyond line 2. Accessing this non-
existing int-object in line 3 invokes undefined behaviour.

You should avoid the use of references, *especially* rvalue
references, if you don't know what you are doing.

Cheers!
SG
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Congress earmarks $30 mil to fight piracy Mary Hanna NZ Computing 0 12-16-2009 01:42 AM
MIL cut-off... Herman UK VOIP 2 10-03-2007 02:26 PM
How to report 38 port scans in 1 week from 7.12.12.16 (part of nic.mil)? Muzzy Computer Security 6 03-24-2006 07:52 PM
Problem problem problem :( Need Help Mike ASP General 2 05-11-2004 08:36 AM
CFP: 7th Mil/Aerospace Applications of Programmable Logic Devices International Conference (MAPLD) Richard B. Katz VHDL 0 12-04-2003 06:08 AM



Advertisments