Re: vector swap time complexity
 
On Sep 15, 4:29 pm, "Francesco S. Carta" <entul...@gmail.com> wrote:
On 15 Set, 16:20, Victor Bazarov <v.Abaza...@comAcast.net> wrote:
Is the following code "good" to check an implementation
for the above behavior?
AFAICT, no.
I disagree, if we understand that the goal is to investigate
what a particular implementation actually does, and not
something to be used in production code.
-------
#include <iostream>
#include <vector>
using namespace std;
void dump(vector<char>* pv) {
  size_t* pc = reinterpret_cast<size_t*>(pv);
Huh???   8-O
The only question I have to pose here is the use of size_t.  In
practice, it's probably an adequate choice for almost any
implementation, but formally, anything but a character type
results in undefined behavior.
I have the following in my library, expressedly for such cases:
    //      Dump:
    //      =====
    //
    //!     This is a simple class which can be used to generate a hex
    //!     dump of any object.  (It generates the hex dump all on a
    //!     single line, as a sequence of two byte hex values,
separated
    //!     by spaces.)  In almost all cases, the actual instance of
this
    //!     class will be a temporary, generated as the return value
of
    //!     the function template dump(), so that template type
deduction
    //!     can be used.
    //!
    //!     \warning
    //!         This class does <strong>not</strong> save a copy of
the
    //!         object, but only a reference to it.  This means that
it
    //!         will contain a dangling reference if the object ceases
to
    //!         exist before the instance of the class.  On the other
    //!         hand, it also means that it is possible to dump the
memory
    //!         of objects which cannot be copied, a signaling NaN,
for
    //!         example.  It is, however strong recommended that only
    //!         temporary instances of this class be used (and that no
    //!         instance be bound to a reference, other than as a
function
    //!         argument); the rules concerning the lifetime of
temporarys
    //!         make this always safe.
    //
---------------------------------------------------------------------------
    template< typename T >
    class Dump : Gabi::Util::IOStreamOperators< Dump< T > >
    {
    public:
        explicit            Dump( T const& obj ) ;
        void                print( std::ostream& dest ) const ;
        //!@cond implementation
    private:
        unsigned char const*myObj ;
        //!@endcond
    } ;
    //!     Allows the use of template type deduction, i.e.:
    //!     \code
    //!         std::cout << dump( someObject ) ;
    //!     \endcode
    //!     rather than
    //!     \code
    //!         std::cout << Dump< ObjectType >( someObject ) ;
    //!     \endcode
    //!
    //!     \param obj
    //!         The object for which an instance of Dump<T> is
desired.
    //!
    //!     \return
    //!         The instance of Dump<T>.
    //
---------------------------------------------------------------------------
    template< typename T >
    inline Dump< T >
    dump(
        T const&            obj )
    {
        return Dump< T >( obj ) ;
    }
    template< typename T >
    Dump< T >::Dump(
        T const&            obj )
        :   myObj( reinterpret_cast< unsigned char const* >( &obj ) )
    {
    }
    template< typename T >
    void
    Dump< T >::print(
        std::ostream&       dest ) const
    {
        IOSave              saver( dest ) ;
        dest.fill( '0' ) ;
        dest.setf( std::ios::hex, std::ios::basefield ) ;
        char const*         baseStr = "" ;
        if ( (dest.flags() & std::ios::showbase) != 0 ) {
            baseStr = "0x" ;
            dest.unsetf( std::ios::showbase ) ;
        }
        unsigned char const* const
                            end = myObj + sizeof( T ) ;
        for ( unsigned char const* p = myObj ; p != end ; ++ p ) {
            if ( p != myObj ) {
                dest << ' ' ;
            }
            dest << baseStr << std::setw( 2 ) << (unsigned int)
( *p ) ;
        }
    }
(Note that the class template IOStreamOperators generates the <<
and >> operators automatically, and IOSave, of course, saves the
various formatting information, and restores it in its
destructor.)
Again, I don't think I've ever used it in production code, but
it's often useful for checking assumptions about the
implementation (big endian or little, are doubles IEEE, etc.).
    [...]
BTW, should I have preferred a C-style cast such as
"(size_t*)pv" instead of reinterpret_cast, in such a cheat?
Absolutely not.  The purpose of reinterpret_cast is to allow
such cheats.  And to make them visible as such.
--
James Kanze