I have the following class:
class Utf8Writer {
struct ZoneData {
uint32_t begin; // codepoint inicial.
uint32_t end; // codepoint final.
};
const ZoneData *findCodepoint( uint32_t cp, FontId fid );
};
const ZoneData *Utf8Writer::findCodepoint( uint32_t cp, FontId fid ) {
auto iter = std::find_if( fid->cbegin( ), fid->cend( ), [cp] ( ZoneData i ) { return ( cp >= i.begin ) && ( cp <= i.end ); } );
return ( iter == fid->cend( ) ) ? nullptr : &( *iter );
}
It works perfectly, except that it is a bug . What I really wanted to do is:
const ZoneData *Utf8Writer::findCodepoint( uint32_t cp, FontId fid ) {
auto iter = std::find_if( fid->cbegin( ), fid->cend( ), [cp] ( const ZoneData &i ) { return ( cp >= i.begin ) && ( cp <= i.end ); } );
return ( iter == fid->cend( ) ) ? nullptr : &( *iter );
}
In fact, if we look at the doc of std::find_if( )
:
template< class InputIt, class UnaryPredicate > InputIt find_if( InputIt first, InputIt last, UnaryPredicate p );
being UnaryPredicate
->bool pred( const Type &a );
I understand that, in the first version, the compiler creates a temporary, calling the default-copy constructor . It turns out that the class ZoneData
is more complex than shown: it includes std::vector
and other things , and its copy is not trivial (neither in time nor in memory usage).
- Is it possible to avoid creating temporary lambda calls , for future occasions, without touching the class
ZoneData
?
It might be a good idea to use a
static_assert
that fails if the lambda parameter is not a reference, to achieve this we need to use the header<type_traits>
and its utilitystd::is_reference
:This code will fail:
While this one should work without a problem: