Sie können sogar constexpr
verwenden, die aufgerufen werden kann, wenn ein constexpr
Objekt initialisiert wird. Füllen Arrays ist möglich, aber std::array
fehlt einige constexpr
Deklarationen, die mit C++17
eingeführt werden.Im Moment müssen wir auf ein einfaches Array zurückgreifen und dieses dann in eine mit einer Hilfsfunktion to_array
konvertieren, die auch zum Standard/tr2 hinzugefügt wird.
#include <array>
#include <algorithm>
#include <cassert>
// this is from cppreference
namespace detail {
template <class T, std::size_t N, std::size_t... I>
constexpr std::array<std::remove_cv_t<T>, N>
to_array_impl(T (&a)[N], std::index_sequence<I...>)
{
return { {a[I]...} };
}
}
template <class T, std::size_t N>
constexpr std::array<std::remove_cv_t<T>, N> to_array(T (&a)[N])
{
return detail::to_array_impl(a, std::make_index_sequence<N>{});
}
constexpr auto make()
{
int a[256] = {-1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,};
for(size_t i=4, n=16, start=16; i <= 7; ++i, n *= 2)
{
for(size_t j=0; j != n; ++j)
{
a[start + j] = i;
}
start += n;
}
return to_array(a);
}
int main() {
static const int LogTable256[256] =
{
#define LT(n) n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n
-1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
LT(4), LT(5), LT(5), LT(6), LT(6), LT(6), LT(6),
LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7)
};
auto constexpr a = make();
assert(std::equal(std::begin(a), std::end(a), std::begin(LogTable256)));
return 0;
}
auto constexpr a = make()
stellt sicher, dass die Tabelle kompiliert Zeitwert ist. A auto const a = make()
funktioniert auch, aber möglicherweise nicht zur Kompilierzeit ausgewertet.
Eine einfachere Implementierung besteht darin, eine Klasse mit einem costexpr
-Konstruktor zu verwenden, der die Tabelle enthält. Die Berechnung ist vollständig kompiliert.
class LogTable
{
public:
constexpr LogTable()
{
for(size_t i=4, n=16, start=16; i <= 7; ++i, n *= 2)
{
for(size_t j=0; j != n; ++j)
{
a[start + j] = i;
}
start += n;
}
}
constexpr int operator[](size_t i) const
{
return a[i];
}
private:
int a[256] = {-1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,};
};
int main() {
static const int LogTable256[256] =
{
#define LT(n) n, n, n, n, n, n, n, n, n, n, n, n, n, n, n, n
-1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
LT(4), LT(5), LT(5), LT(6), LT(6), LT(6), LT(6),
LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7), LT(7)
};
LogTable constexpr l;
for(auto i=0; i != 256; ++i)
{
assert(LogTable256[i] == l[i]);
}
return 0;
}
Sie kopieren diesen viel Code in eine leere Datei & run (falls vorhanden) dieser Befehl "' g ++ -E file.cpp> file_preprocessed.cpp'", können Sie sehen, dass die' LT (n) ' Makro hätte es in jedem Fall mit 16 ns ersetzt. Es scheint, dass jemand 'char' mit solchen ASCII-basierten Werten speichert. Bei Schleifen gibt es keinen systematischen Weg, diese Sequenz zu erzeugen, daher ist es besser links wie oben. – iammilind
LT (n) wird für jeden Wert durch 8 ersetzt. Sie können also einfach for-Schleifen für i> 4 verwenden; besser Sie versuchen es selbst und zeigen Sie uns Ihre Fortschritte –
@RamandeepPunia 16 mal, eigentlich. Sie erhalten am Ende -1, dann eine Liste von 255 Werten, wo Sie immer 2^n Instanzen von n für n von 0 bis 7 finden. – starturtle