Extract data without using extra variables

2

I want to extract a data from a class; Currently, I use an auxiliary variable for it.

To work, it works ... but I was wondering if it could be done in another way, saving me the variable inside the function Envoltura::result( ) :

#include <iostream>

struct Base {
  void ( *move )( Base *, void * );

  inline Base( void ( *m )( Base *, void * ) ) : move( m ) { }
};

template< typename T > struct Derivada : public Base {
  T value;

  static inline void do_move( Base *b, void *p ) {
    Derivada *d = static_cast< Derivada * >( b );
    new ( p ) T( std::move( d->value ) );
  }

  inline Derivada( ) : Base( do_move ), value( 10 ) { }
};

template< typename T > struct Envoltura {
  Base *base;

  inline T result( ) {
    union {
      T tmp;
      char dummy;
    };

    base->move( base, &tmp );
    return tmp;
  }

  inline Envoltura( ) : base( new Derivada< T >( ) ) { }
};

int main( ) {
  Envoltura< int > e;
  int result = e.result( );

  std::cout << "Resultado: " << result << std::endl;

  return 0;
}

Compiled with g++ -std=c++11 -Wall -Wextra -pedantic

EDITO

It is necessary to maintain the class hierarchy exposed: a Base , a template< > Derivada daughter of the first, and a third template< > Envoltura if inheritance of the previous ones. And no I can use virtual functions.

    
asked by Trauma 15.03.2018 в 21:13
source

1 answer

2

I, at first, would try not to convert the data until the end to avoid, as far as possible, copying values. Copying pointers ...

inline T result( ) {
  void * tmp;

  base->move( base, tmp );
  return static_cast<T>(*tmp);
}

Also, you could benefit from the use of the move syntax (if implemented) or the copy omission ( copy elision ).

Even so, you still have a temporary variable ... to eliminate it, it would be necessary to modify the design a bit:

struct Base {
  using FuncPtr = void*(*)(Base*);
  FuncPtr move;

  inline Base( FuncPtr m ) : move( m ) { }
};

template< typename T > struct Derivada : public Base {
  T value;

  static inline void* do_move(Base *b) {
    Derivada *d = static_cast< Derivada * >( b );
    return &(d->value);
  }

  inline Derivada( ) : Base( do_move ), value( 10 ) { }
};

template< typename T > struct Envoltura {
  Base *base;

  inline T result( ) {
    return std::move(*static_cast<T*>(base->move(base)));
  }

  inline Envoltura( ) : base( new Derivada<T> ) { }
};

Now the value is not extracted by an argument but via return . The class Envoltura is then limited to convert the value in the type that interests at each moment.

    
answered by 15.03.2018 / 21:41
source