1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
|
#include <array>
#include <initializer_list>
#include <utility>
#include <stdexcept>
template < typename T >
using position_value_pairs = std::initializer_list< std::pair<std::size_t,T> > ;
template < typename T, std::size_t N >
std::array<T,N> make_tags( position_value_pairs<T> ilist )
{
std::array<T,N> tags{} ;
for( const auto& pair : ilist )
{
if( pair.first >= N ) throw std::out_of_range( "invalid position" ) ;
else tags[pair.first] = pair.second ;
}
return tags ;
}
int foo()
{
auto my_tags = make_tags<char,20>( { { 3, 'A' }, { 7, 'B' }, { 12, 'C' } } ) ;
return +my_tags[3] + my_tags[5];
}
/*
foo():
mov eax, 65
ret
*/
int bar()
{
auto my_tags = make_tags<char,20>( { { 3, 'A' }, { 7, 'B' }, { 12, 'C' } } ) ;
for( int i : { 5, 9, 13, 17 } ) if( my_tags[i] == 0 ) my_tags[i] = 1 ;
return +my_tags[3] + my_tags[5];
}
/*
bar():
mov QWORD PTR [rsp-40], 0
mov BYTE PTR [rsp-37], 65
movsx eax, BYTE PTR [rsp-37]
mov BYTE PTR [rsp-35], 1
movsx edx, BYTE PTR [rsp-35]
add eax, edx
ret
*/
// a really good optimiser could have generated (assuming that as before 'A' == 65):
/*
bar():
mov eax, 66
ret
*/
// g++ is not terrible; copying of the array and redundant out of range checks have still been elided
|