代码之家  ›  专栏  ›  技术社区  ›  Potatoswatter

绑定对对象或虚拟对象的引用时的样式

  •  5
  • Potatoswatter  · 技术社区  · 15 年前

    A &&var_or_dummy = modify? static_cast<A&&>( my_A )
                             : static_cast<A&&>( static_cast<A>( my_A ) );
    

    static_cast my_A

    const

    A &&var_or_dummy = modify? std::move( my_A )
                             : static_cast<A&&>( A( my_A ) );
    

    move : A(my_A)

    A &&var_or_dummy = modify? (A&&)( my_A ) : (A&&)( A( my_A ) );
    

    true

    A

    V

    #define VAR_OR_DUMMY( C, V ) ( (C)? \
      static_cast< typename std::remove_reference< decltype(V) >::type && >( V ) \
    : static_cast< typename std::remove_reference< decltype(V) >::type && >   (  \
      static_cast< typename std::remove_reference< decltype(V) >::type >( V ) ) )
    

    3 回复  |  直到 15 年前
        1
  •  2
  •   Roger Pate    15 年前

    只需使用一个额外的函数调用来避免整个混乱:

    void f(bool modify, A &obj) {
      return [&](A &&obj) {
        real();
        work();
      }(modify ? std::move(obj) : std::move(A(obj)));
    }
    

    而不是:

    void f(bool modify, A &obj) {
      A &&var_or_dummy = /* ??? */;
      real();
      work();
    }
    

    它是 lambdas, lambdas, everywhere !

        2
  •  2
  •   sellibitze    15 年前

    我认为你的方法有两个问题。

    你依赖行为

    int   i = 0;
    int&  j = true?      i  :      i;
    int&& k = true? move(i) : move(i);
    assert(&i == &j); // OK, Guaranteed since C++98
    assert(&i == &k); // Does this hold as well?
    

    当前标准草案N3126包含5.16/4:

    如果第二个和第三个操作数[条件运算符]是相同值类别的glvalues并且具有相同的类型,则结果是该类型和值类别

    这使我认为上述两个断言应该成立。但是使用GCC4.5.1,第二个失败。我相信这是一个GCC错误。

    此外,您还依赖编译器来延长临时对象的生命周期。 y 在以下示例中引用:

    A func();
    
    A&& x = func();                   // #1
    A&& y = static_cast<A&&>(func()); // #2
    

    x 不会是悬而未决的参考 但我不太确定 Y . 我认为关于延长时间的规则只适用于初始值设定项表达式是 纯净的 价值观。至少,这将大大简化实现。此外,海湾合作委员会似乎也同意我的看法。在第二种情况下,gcc不会延长临时对象的生命周期。在你的方法中,这将是一个悬而未决的参考问题。 .

    更新: 根据12.2/5,在这两种情况下,临时物体的寿命都应该延长,1和2。例外列表中的所有要点在这里似乎都不适用。在这方面,海湾合作委员会似乎又有问题。

    解决问题的一个简单方法是:

    vector<A> tempcopy;
    if (!modify) tempcopy.push_back(myA);
    A& ref = modify ? myA : tempcopy.back();
    

    或者,您可以使用boost::scoped_ptr而不是向量。

        3
  •  0
  •   Potatoswatter    15 年前

    XValue安全性的问题可以通过为表达式内部的使用提供一个替代方案来解决。问题完全不同,现在我们 不要 需要XValue结果,可以使用函数:

    template< typename T >
    T &var_or_dummy( bool modify, T &var, T &&dummy = T() ) {
        if ( modify ) return var;
        else return dummy = var;
    }
    
        maybe_get_result( arg, var_or_dummy( want_it, var ) );
    

    现在类型必须是默认的可构造类型,并且始终构造虚拟对象。对副本进行条件评估。我不认为我真的想处理做了太多这件事的代码。

    Boost Optional 有点帮助;它只需要可复制构造的t:

    template< typename T >
    T &var_or_dummy( bool modify, T &var,
                     boost::optional< T > &&dummy = boost::optional< T >() ) {
        if ( modify ) return var;
        else return dummy = var;
    }
    

    可选的是有用的,但是它与C++ 0x结合有一些重叠。重新实现并不难。

    template< class T >
    struct optional_union {
        bool valid;
        union storage {
            T obj; // union of one non-POD member simply reserves storage
    
            storage() {} // uh, what could the constructor/destructor possibly do??
            ~storage() {}
        } s;
    
        optional_union() : valid( false ) {}
        optional_union &operator=( T const &in ) {
            new( &s.obj ) T( in ); // precondition: ! valid
            valid = true;
            return *this; 
        }
        ~optional_union()
            { if ( valid ) s.obj.~T(); }
    };
    
    template< typename T >
    T &var_or_dummy( bool modify, T &var,
                     optional_union< T > &&dummy = optional_union< T >() ) {
        if ( modify ) return var;
        else return ( dummy = var ).s.obj;
    }
    

    这个 optional_union 类只够用于这个应用程序,显然它可以扩展很多。