は、発電機への入力の任意の範囲を可能にする別の方法です:
ここでは、ユースケースです:ここで
/// generate an integer by multiplying the input by 2
/// this could just as easily be a lambda or function object
constexpr int my_generator(int x) {
return 2 * x;
}
int main()
{
// generate a std::array<int, 64> containing the values
// 0 - 126 inclusive (the 64 acts like an end() iterator)
static constexpr auto arr = generate_array(range<int, 0, 64>(),
my_generator);
std::copy(arr.begin(), arr.end(), std::ostream_iterator<int>(std::cout, ", "));
std::cout << std::endl;
}
それは
#include <utility>
#include <array>
#include <iostream>
#include <algorithm>
#include <iterator>
/// the concept of a class that holds a range of something
/// @requires T + 1 results in the next T
/// @requires Begin + 1 + 1 + 1.... eventually results in Tn == End
template<class T, T Begin, T End>
struct range
{
constexpr T begin() const { return Begin; }
constexpr T end() const { return End; }
constexpr T size() const { return end() - begin(); }
using type = T;
};
/// offset every integer in an integer sequence by a value
/// e.g offset(2, <1, 2, 3>) -> <3, 4, 5>
template<int Offset, int...Is>
constexpr auto offset(std::integer_sequence<int, Is...>)
{
return std::integer_sequence<int, (Is + Offset)...>();
}
/// generate a std::array by calling Gen(I) for every I in Is
template<class T, class I, I...Is, class Gen>
constexpr auto generate_array(std::integer_sequence<I, Is...>, Gen gen)
{
return std::array<T, sizeof...(Is)> {
gen(Is)...
};
}
/// generate a std::array by calling Gen (x) for every x in Range
template<class Range, class Gen>
constexpr auto generate_array(Range range, Gen&& gen)
{
using T = decltype(gen(range.begin()));
auto from_zero = std::make_integer_sequence<typename Range::type, range.size()>();
auto indexes = offset<range.begin()>(from_zero);
return generate_array<T>(indexes, std::forward<Gen>(gen));
}
/// generate an integer by multiplying the input by 2
constexpr int my_generator(int x) {
return 2 * x;
}
int main()
{
static constexpr auto arr = generate_array(range<int, 0, 64>(),
my_generator);
std::copy(arr.begin(), arr.end(), std::ostream_iterator<int>(std::cout, ", "));
std::cout << std::endl;
}
を機能できるようにするために定型がここにいます組み立て前に見たコードが膨らんでいる:
.LC0:
.string ", "
main:
;; this is the start of the code that deals with the array
pushq %rbx
movl main::arr, %ebx
.L2:
movl (%rbx), %esi
movl std::cout, %edi
addq $4, %rbx
;; this is the end of it
;; all the rest of this stuff is to do with streaming values to cout
call std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
movl $2, %edx
movl $.LC0, %esi
movl std::cout, %edi
call std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
cmpq main::arr+256, %rbx
jne .L2
movl std::cout, %edi
call std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&)
xorl %eax, %eax
popq %rbx
ret
subq $8, %rsp
movl std::__ioinit, %edi
call std::ios_base::Init::Init()
movl $__dso_handle, %edx
movl std::__ioinit, %esi
movl std::ios_base::Init::~Init(), %edi
addq $8, %rsp
jmp __cxa_atexit
main::arr:
.long 0
.long 2
.long 4
.long 6
.long 8
.long 10
.long 12
.long 14
.long 16
.long 18
.long 20
.long 22
.long 24
.long 26
.long 28
.long 30
.long 32
.long 34
.long 36
.long 38
.long 40
.long 42
.long 44
.long 46
.long 48
.long 50
.long 52
.long 54
.long 56
.long 58
.long 60
.long 62
.long 64
.long 66
.long 68
.long 70
.long 72
.long 74
.long 76
.long 78
.long 80
.long 82
.long 84
.long 86
.long 88
.long 90
.long 92
.long 94
.long 96
.long 98
.long 100
.long 102
.long 104
.long 106
.long 108
.long 110
.long 112
.long 114
.long 116
.long 118
.long 120
.long 122
.long 124
.long 126
つまり、何もありません。
* "bloating executable size" *あなたはそれについては確かですか? –
私はこれを多くの場所で行いますが、そのような初期化のために追加機能が必要になります。決定的な項目ではないが、それでもなお。この質問は、研究の関心事によく似ています。 – Mikhail
'constexpr'ジェネレータを正しく使用すると、実行可能なサイズに影響しません。限り、コンパイルを遅くするように、まあ、C + +を歓迎します。 –