Re: New tricks in C++11 that you have found?
On 02.02.2012 18:37, Juha Nieminen wrote:
What are some new fancy tricks that you have found with C++11?
Perhaps something that was either just outright impossible with C++98
or much more difficult/laborious. (And naturally I'm not just talking
about things like "being able to write 'auto' instead of a long type
name", but less obvious tricks.)
I find that using lambdas it's possible to express many things more
cleanly and centralized and DRY, at the cost of sometimes slightly more
verbose code.
E.g., capturing a common "pattern" for invoking Windows API functions,
<code>
#undef UNICODE
#define UNICODE
#undef NOMINMAX
#define NOMINMAX
#include <windows.h>
#include <iostream>
#include <string>
#include <stddef.h>
#include <stdexcept>
#include <stdlib.h>
#include <functional>
using namespace std;
#ifdef _MSC_VER
# define CPP_NORETURN __declspec( noreturn )
# pragma warning( disable: 4646 ) // non-void return type
#else
# define CPP_NORETURN
#endif
#define CPP_NOTHROW throw()
typedef ptrdiff_t Size;
typedef Size Index;
bool hopefully( bool const v ) CPP_NOTHROW { return v; }
CPP_NORETURN bool throwX( string const& s ) { throw runtime_error( s ); }
#if 0
DWORD WINAPI GetEnvironmentVariable(
__in_opt LPCTSTR lpName,
__out_opt LPTSTR lpBuffer,
__in DWORD nSize
);
#endif
wstring stringResult(
char const functionIdForErrorMsg[],
function< Size( wchar_t*, Size ) > const& getText,
function< Size() > const& getBufferSize = nullptr
)
{
SetLastError( 0 );
Size const bufSize = (
!getBufferSize? getText( nullptr, 0 ) : getBufferSize()
);
hopefully( bufSize > 0 && GetLastError() == 0 )
|| throwX(
string() + functionIdForErrorMsg + " failed (getting buffer
size)"
);
wstring result( bufSize, L'@' );
SetLastError( 0 );
Size const n = getText( &result[0], result.size() );
hopefully( n >= 0 && GetLastError() == 0 )
|| throwX(
string() + functionIdForErrorMsg + " failed (getting text)"
);
result.resize( n );
return result;
}
namespace env {
wstring value( wstring const& name )
{
auto const getText = [&name]( wchar_t* pBuf, Size bufSize ) -> Size
{
Size const nCharacters =
GetEnvironmentVariable( name.c_str(), pBuf, bufSize );
return (nCharacters == 0? -1 : nCharacters);
};
return stringResult( "env::value: GetEnvironment", getText );
}
} // namespace env
namespace gui {
wstring windowText( HWND const window )
{
auto const getText = [window]( wchar_t* pBuf, Size bufSize )
{ return GetWindowText( window, pBuf, bufSize ); };
auto const getBufferSize = [window]()
{ return 1 + GetWindowTextLength( window ); };
return stringResult(
"gui::windowText: GetWindowText", getText, getBufferSize
);
}
} // namespace gui
int main()
{
try
{
wcout << env::value( L"windir" ) << endl;
wcout << gui::windowText( GetForegroundWindow() ) << endl;
return EXIT_SUCCESS;
}
catch( exception const& x )
{
wcerr << "!" << x.what() << endl;
}
return EXIT_FAILURE;
}
</code>
Cheers,
- Alf