Tag Archives: C++

Scott Meyers Video – Universal References

Scott Meyers posted a video of his Universal References presentation from C++ and Beyond 2012. There’s also an article on the subject in the ACCU magazine Overload Issue 111, but I found the video much clearer (and more entertaining).

Meyers coined the term ‘Universal References’ for instances where the type of a variable or parameter is declared T&& and where T is a deduced type. It may look like an rvalue-reference, but it can also match lvalue-references:

20130813-122646.jpg

so it’s usually a mistake to overload on both T&& and const T& in a template function. Another key point is that, whereas an overload with an rvalue-reference would call std::move (e.g. a move constructor where T is not deduced), an overload with a universal-reference should call std::forward (because you don’t yet know if it’s an rvalue- or lvalue-reference):

20130813-123009.jpg

He also summarises the reference-collapsing rules as “lvalue-references are infectious”, a handy mnemonic from Stephan T. Lavavej.

1 Comment

Filed under C++, Programming, Video

std::sort now guarantees complexity O(N * log N) under C++11 Standard

I learnt recently that in the C++11 Standard, std::sort is required to have complexity O(N * log N) – not “on average N * log N with a worst case O(n^2)”, but guaranteed O(N * log N). This follows David Musser’s paper on Introspective Sorting and Selection.

Musser’s IntroSort uses QuickSort, but also monitors the number of partitions that have occurred. For example, one might use “median-of-3” to pick each pivot, but that could cause the O(N^2) behaviour if pathological sequence is encountered. In the paper, such a sequence is described by construction. IntroSort switches to HeapSort (which guarantees O(N * log N) performance) once the number of QuickSort partitions reaches 2 * log N. Musser proves that the overall algorithm performance remains O(N * log N).

As pointed out on StackOverflow, std::nth_element could be re-implemented with similar benefits:

Ideally exactly the same should apply std::nth_element but the ISO C++ 2011 standard has not tightened up the complexity requirements. So std::nth_element could be O(N * N) in the worst case.

Leave a comment

Filed under C++, Programming

Why call std::move on a variable that is already T&&?

A StackOverflow question asks why it is necessary to call std::move on a parameter when implementing a move constructor, given that the parameter is already declared T&&?

Named rvalue references are lvalues. Unnamed rvalue references are rvalues.

In other words, if you don’t explicitly move a into b X b = std::move(a); then you haven’t declared that you’ve finished with a, which is a named variable – so the compiler will call X’s copy constructor instead of X’s move constructor.

Leave a comment

Filed under C++, Programming

“Contextually converted to bool”

Chris Sharpe blogged an example of how marking operator bool() explicit neededn’t necessitate any overhead when using that type in a simple if condition:

An expression e can be implicitly converted to a type T if and only if the declaration T t=e; is well-formed, for some invented temporary variable t (8.5). Certain language constructs require that an expression be converted to a Boolean value. An expression e appearing in such a context is said to be contextually converted to bool and is well-formed if and only if the declaration bool t(e); is well-formed, for some invented temporary variable t (8.5). The effect of either implicit conversion is the same as performing the declaration and initialization and then using the temporary variable as the result of the conversion.

Leave a comment

Filed under C++, Programming

Optimizing C++ code (Visual C++ Team blog)

The Visual C++ Team blog has started a series on Optimizing C++ code.

  1. Introduction
  2. Overview
  3. Constant Folding
  4. Dead Code Elimination

Leave a comment

Filed under C++, Programming

Universal memorisation for C++

ISOCpp linked to a StackOverflow question about universal memorisation.

Leave a comment

Filed under C++, Programming

New Concepts Lite paper (2nd revision)

The ISOCpp blogposted a link to the latest Concepts Lite paper.

Leave a comment

Filed under C++, Programming

Runtime-sized arrays v std::dynarray in C++ 14

Interesting question on StackOverflow regarding the differences between the proposals in C++14 for std::dynarray and runtime-sized arrays.

Leave a comment

Filed under C++, Programming

How to serialize a COM object as a Base64 byte array

A component I’m working on needs to be able to serialize its data via JSON.  That’s fine for scalars, arrays and maps, but we also needed to be able to serialize COM objects (there’s a large legacy codebase underneath, much of which is deployed via COM).  It turns out ATL provides API functions for Base 64 encoding (which was a surprise to me and a number of my colleagues).  Here’s some code to make calling it easier (I’ve replaced the production code error handling with simple strings):

std::string to_base_64(int byte_length, const void* bytes  )
{
  if (bytes == 0)
    throw "ToBase64 called with zero bytes";
  
  ATL::CStringA base64;
  int base64_length = ATL::Base64EncodeGetRequiredLength(byte_length);

  if(!ATL::Base64Encode(static_cast<const BYTE*>(bytes), 
                        byte_length, 
                        base64.GetBufferSetLength(base64_length), 
                        &base64_length))
    throw "ATL::Base64Encode failed";

  base64.ReleaseBufferSetLength(base64_length);
  return static_cast<const char*>(CT2A(base64));
}

std::pair<size_t,std::unique_ptr<BYTE>> from_base_64( const std::string& encoded )
{
  // Predict length needed for decoding
  int decoded_length = Base64DecodeGetRequiredLength( encoded.size() );
  std::unique_ptr<BYTE> buffer( new BYTE[decoded_length] );

  // Actual decoded-length may be different to that predicted - method overwrites the value
  if (!Base64Decode(encoded.c_str(), encoded.size(), buffer.get(), &decoded_length))
  {
    throw "ATL::Base64Decode failed";
  }

  return std::make_pair( decoded_length, std::move(buffer) );
}

That leaves the requirement to turn a serializable COM object into a byte array.  The following code does the job provided the COM object implements IPersistStream:

std::pair<size_t, std::unique_ptr<BYTE>> object_to_bytes( IUnknown* pUnk )
{
  // Create an in-memory stream, HGlobalMem will be allocated internally
  HRESULT hr;
  CComPtr<IStream> pIStream;

  if (FAILED(hr = CreateStreamOnHGlobal(0, TRUE, &pIStream)))
    throw "Could not CreateStreamOnHGlobal";

  CComPtr<IPersistStream> pPersistStream;
  if (FAILED(hr = pUnk->QueryInterface(IID_IPersistStream, &pPersistStream ) )
    throw "Failed to QI to IPersistStream";

  CLSID clsid;
  if (FAILED(hr = pPersistStream->GetClassID(&clsid) )
    throw "Failed to get clsid";

  // Serialise CLSID into stream
  if (FAILED(hr = WriteClassStm( pIStream, clsid )))
    throw "WriteClassStm failed";

  // Serialise object into stream
  if (FAILED(hr = pPersistStream->Save( pIStream, TRUE ) )
    throw "Save object into IPersistStream failed";

  // Find out how big the stream is
  LARGE_INTEGER liStart = {0};
  if (FAILED(hr = pIStream->Seek( liStart, STREAM_SEEK_SET, NULL ) )
    throw "IPersistStream::Seek failed";

  STATSTG statstg;
  memset( &statstg, 0, sizeof(statstg) );

  if (FAILED(hr = pIStream->Stat( &statstg, STATFLAG_NONAME ) )
    throw "IPersistStream::Stat failed";

  // Populate a byte array from the stream
  std::unique_ptr<BYTE> buffer( new BYTE[statstg.cbSize.LowPart] );
  unsigned long size_read;
  if (FAILED(hr = pIStream->Read( (void*)buffer.get(), statstg.cbSize.LowPart, &size_read ) )
    throw "IPersistStream::Read failed";

  ASSERT( size_read == statstg.cbSize.LowPart );

  return std::make_pair( size_read, std::move(buffer) );
}

CComPtr<IUnknown> bytes_to_object( size_t length, void* bytes )
{
  HRESULT hr;
  CComPtr<IStream> pIStream;

  HGLOBAL handle = GlobalAlloc( GMEM_MOVEABLE | GMEM_NODISCARD, length );

  if (FAILED(hr = CreateStreamOnHGlobal(handle, TRUE, &pIStream)))
    throw "Could not CreateStreamOnHGlobal";

  unsigned long size_written;
  if (FAILED(hr = pIStream->Write( bytes, length, &size_written ) )
    throw "Failed to write to stream";

  // Reset the stream
  LARGE_INTEGER liStart = {0};

  if (FAILED(hr = pIStream->Seek( liStart, STREAM_SEEK_SET, NULL ) )
    throw "IPersistStream::Seek failed";

  // Serialise CLSID out of stream
  CLSID clsid;

  if (FAILED(hr = ReadClassStm( pIStream, &clsid )))
    throw "ReadClassStm failed";

  // Create object from the clsid and stream from IStream into the object, using IPersistStream
  CComPtr<IUnknown> pUnk;
  if (FAILED(hr = ::CoCreateInstance(clsid, NULL, CLSCTX_ALL, &pUnk ) )
    throw "Failed to CoCreate clsid";

  CComPtr<IPersistStream> pStream;
  if (FAILED(hr = pUnk->QueryInterface(IID_IPersistStream, &pStream ) )
    throw "Failed to QI to IPersistStream";

  if (FAILED(hr = pStream->Load( pIStream ) )
    throw "IPersistStream::Load failed";

  return pUnk;
}

Then it’s a matter of putting the methods together to achieve a simple API:

std::string to_base64_encoded_byte_array( IUnknown* pUnk )
{
  auto bytes = object_to_bytes( pUnk );
  return to_base_64( bytes.first, bytes.second.get() );
}

CComPtr<IUnknown> from_base64_encoded_byte_array( const std::string& encoded)
{
  auto bytes = from_base_64( encoded );
  return bytes_to_object( bytes.first, bytes.second.get() );
}

Leave a comment

Filed under C++, C++ Code, Programming

How to downcast a shared_ptr

A lot of the codebase I work on is deployed as COM servers. This means that it isn’t uncommon to pass an array of objects as an of pointers to base (i.e. IUnknown) and then downcast to the specific interface you want using QueryInterface.

I found myself in a similar situation with some more modern C++, where I had a std::vector<std::shared_ptr> and wanted to convert each pointer to a shared_ptr in order to call into some API method. The question is – if you have a std::shared_ptr<T1>, how to cast it to a std::shared_ptr<T2>  (for suitably related T1 and T2)?

This question was already asked on StackOverflow and the answers pointed me at std::dynamic_pointer_cast and std::static_pointer_cast, which are analogous to static_cast/dynamic_cast for raw pointers.

class B
{
public:
  virtual void Print(){ std::cout << "Object type B\n"; }
  virtual ~B(){};
};

class C : public B
{
public:
  virtual void Print(){ std::cout << "Object type C\n"; }
  void BehaveLikeC()  {std::cout << "Behave like C\n";}
};

class D : public B
{
public:
  virtual void Print(){ std::cout << "Object type D\n"; }
  void BehaveLikeD() { std::cout << "Behave like D\n"; }
};

void DoSomething( const std::shared_ptr<D>& d )
{
    d->BehaveLikeD();
}

int _tmain(int argc, _TCHAR* argv[])
{
  std::vector<std::shared_ptr<b>> elements;
  elements.push_back( std::make_shared<C>() );
  elements.push_back( std::make_shared<D>() );

  // Call base class method on all elements
  std::for_each( elements.begin(), elements.end(),
    []( const std::shared_ptr<b>& b ){ b->Print(); });

  // Call C behaviour on all C elements
  for ( size_t i = 0; i < elements.size(); ++i )
  {
    auto c = std::dynamic_pointer_cast( elements[i] );
    if (c ){ c->BehaveLikeC(); }

    auto d = std::dynamic_pointer_cast<D>( elements[i] );
    if (d){ DoSomething(d); }
  }

  return 0;
}

1 Comment

Filed under C++, C++ Code, Programming