C++0x - tuple

Discussion in 'C++' started by er, Jun 1, 2011.

  1. er

    er Guest

    Please, why the failed assertion below? Thanks.

    #include <tuple>

    int main()
    {

    std::tuple<int&&> t1( 1 );

    assert( std::get<0>( t1 ) == 1 ); // OK

    std::tuple<std::string, int&&> t2( "a", 1 );

    assert( std::get<1>( t2 ) == 1 ); // Fail

    return 0;
    }

    OS X 10.6 - GCC 4.4
     
    er, Jun 1, 2011
    #1
    1. Advertising

  2. er

    Rune Allnor Guest

    On Jun 1, 4:40 am, er <> wrote:
    > Please, why the failed assertion below? Thanks.
    >
    > #include <tuple>
    >
    > int main()
    > {
    >
    >             std::tuple<int&&> t1( 1 );


    What type is 'int&&' ? The naive intrepretation is that it is
    a reference to a reference. If so, isn't that illegal (or at
    least UB)? Should this compile at all?

    Rune
     
    Rune Allnor, Jun 1, 2011
    #2
    1. Advertising

  3. er

    red floyd Guest

    On 5/31/2011 9:36 PM, Rune Allnor wrote:
    > On Jun 1, 4:40 am, er<> wrote:
    >> Please, why the failed assertion below? Thanks.
    >>
    >> #include<tuple>
    >>
    >> int main()
    >> {
    >>
    >> std::tuple<int&&> t1( 1 );

    >
    > What type is 'int&&' ? The naive intrepretation is that it is
    > a reference to a reference. If so, isn't that illegal (or at
    > least UB)? Should this compile at all?
    >


    I'm not fully up on my C++0x, but isn't it an rvalue-reference?
     
    red floyd, Jun 1, 2011
    #3
  4. er

    Qi Guest

    On 2011-6-1 10:40, er wrote:
    > std::get<1>( t2 )


    How about trace out the value of std::get<1>( t2 )
    to see why the assert failed?

    The assert failed because the value is wrong,
    so it makes sense to see the value.

    --
    WQ
     
    Qi, Jun 1, 2011
    #4
  5. On Jun 1, 7:36 am, Rune Allnor <> wrote:
    > On Jun 1, 4:40 am, er <> wrote:
    >
    > > Please, why the failed assertion below? Thanks.

    >
    > > #include <tuple>

    >
    > > int main()
    > > {

    >
    > >             std::tuple<int&&> t1( 1 );

    >
    > What type is 'int&&' ? The naive intrepretation is that it is
    > a reference to a reference. If so, isn't that illegal (or at
    > least UB)? Should this compile at all?
    >
    > Rune


    Hi

    Actually, int&& is r-value reference. It's like traditional
    l-value reference, but it can bind to r-value. Consider:
    int i = 1; // referent (l-value)
    int& ir = i; // ir is a reference to i
    int& ir2 = int(); // error int() is a temporary object
    // and it's r-value
    int&& ir3 = int(); // OK: binding r-value reference to r-value
    R-value reference is a foundation for a new feature of
    C++0x, called move semantics.
    You can use such feature in Visual Studio 2010 or
    gcc 4.5.0 or above.

    Regards,
    -- Saeed Amrollahi
     
    Saeed Amrollahi, Jun 1, 2011
    #5
  6. On Jun 1, 5:40 am, er <> wrote:
    > Please, why the failed assertion below? Thanks.
    >
    > #include <tuple>
    >
    > int main()
    > {
    >
    >             std::tuple<int&&> t1( 1 );
    >
    >            assert( std::get<0>( t1 ) == 1 ); // OK
    >
    >             std::tuple<std::string, int&&> t2( "a", 1 );
    >
    >            assert( std::get<1>( t2 ) == 1 ); // Fail
    >
    >            return 0;
    >
    > }
    >
    > OS X 10.6 - GCC 4.4


    I ran you program under Ubuntu & gcc 4.6.0
    with the following command
    gcc -std=c++0x -pedantic tuple_test.c++ -o tuple_test
    and it's OK. Actually with the following program:
    #include <cassert>
    #include <tuple>
    #include <iostream>

    int main()
    {
    using namespace std;
    tuple<int&&> t1(1);
    assert(get<0>(t1) == 1);
    tuple<string, int&&> t2("a", 1);
    assert(get<1>(t2) == 1);
    cout << get<0>(t2) << '\t' << get<1>(t2) << '\n';
    return 0;
    }

    I have the following output:
    a 1

    Regards,
    -- Saeed Amrollahi
     
    Saeed Amrollahi, Jun 1, 2011
    #6
  7. er

    Balog Pal Guest

    "er" <>
    > Please, why the failed assertion below? Thanks.
    >
    > #include <tuple>
    >
    > int main()
    > {
    > std::tuple<int&&> t1( 1 );
    > assert( std::get<0>( t1 ) == 1 ); // OK
    > std::tuple<std::string, int&&> t2( "a", 1 );
    > assert( std::get<1>( t2 ) == 1 ); // Fail
    > return 0;
    > }


    tuple is a value type. You try to use it with reference. That will not
    likely work in general.

    In particular your tuple will have a member of reference type, that will be
    bound to a temporary. That temporary is destroyed at the end of the line, so
    you have a dongling reference and attached undefined behavior on its use.

    Lifetime of a reference extends the lifetime of the temporary if done
    directly:
    int && i1 = getI();
    const int & i2 = getI();

    But it does not happen if you pass the ref to a function -- including a
    different object's constructor.
     
    Balog Pal, Jun 1, 2011
    #7
  8. er

    SG Guest

    On 1 Jun., 04:40, er wrote:
    >
    >       std::tuple<int&&> t1( 1 );


    creates a tuple that stores a DANGLING REFERENCE since the temporary
    int object storing the one will be destroyed "after the semicolon".

    >        assert( std::get<0>( t1 ) == 1 ); // OK


    You're invoking undefined behaviour due to the danling reference.

    >       std::tuple<std::string, int&&> t2( "a", 1 );
    >
    >        assert( std::get<1>( t2 ) == 1 ); // Fail


    That's what you get for undefined behaviour. Plain and simple.

    In both cases a temporary int object will be created which stores the
    number 1 and will stop existing after the semicolon. Therefore, the
    "reference member" of the tuple becomes invalid. Any access invokes
    undefined behaviour.

    Cheers!
    SG
     
    SG, Jun 1, 2011
    #8
  9. er

    er Guest

    On Jun 1, 5:02 am, SG <> wrote:
    > On 1 Jun., 04:40, er wrote:
    >
    >
    >
    > >        std::tuple<int&&> t1( 1 );

    >
    > creates a tuple that stores a DANGLING REFERENCE since the temporary
    > int object storing the one will be destroyed "after the semicolon".
    >
    > >        assert( std::get<0>( t1 ) == 1 ); // OK

    >
    > You're invoking undefined behaviour due to the danling reference.
    >


    Thanks, but this

    std::cout << std::get<1> ( std::tuple<std::string, int&&>( "a",
    1 ) ) << std::endl;

    outputs 0, and this

    assert(
    std::get<1>(
    std::tuple<std::string, int&&>( "a", 1 )
    ) == 1
    );

    fails
     
    er, Jun 1, 2011
    #9
  10. er

    SG Guest

    On 1 Jun., 15:21, er <> wrote:
    > Thanks, but this
    >
    >   std::cout << std::get<1> ( std::tuple<std::string, int&&>( "a",
    > 1 ) )  << std::endl;
    >
    > outputs 0, and this
    >
    >   assert(
    >        std::get<1>(
    >            std::tuple<std::string, int&&>( "a", 1 )
    >        ) == 1
    >   );
    >
    > fails


    Sorry, but I don't see why this would be the case and I'm not able to
    reproduce this. See http://ideone.com/yxcIi

    Cheers!
    SG
     
    SG, Jun 1, 2011
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Michal Mikolajczyk
    Replies:
    1
    Views:
    812
    Larry Bates
    Apr 20, 2004
  2. Jeff Epler
    Replies:
    0
    Views:
    961
    Jeff Epler
    Apr 20, 2004
  3. Bill Scherer
    Replies:
    0
    Views:
    615
    Bill Scherer
    Apr 20, 2004
  4. Gregor Horvath

    Why tuple with one item is no tuple

    Gregor Horvath, Mar 15, 2005, in forum: Python
    Replies:
    37
    Views:
    829
    Antoon Pardon
    Mar 30, 2005
  5. Steve
    Replies:
    1
    Views:
    970
    Fredrik Lundh
    Dec 13, 2005
Loading...

Share This Page