Po niektóre kopania wygląda użyciu std::initializer_list
jest nie możliwe w GCC 4.7 ze względu na brak constexpr
w deklaracji jest to. To powinien współpracować z GCC 4.8 jako <initializer_list>
został zaktualizowany o constexpr
. Niestety używanie GCC 4.8 nie jest obecnie możliwe.
Możliwe jest uzyskanie dostępu do elementów tablicy, jeśli zepsuty wskaźnik jest przekazywany przez odwołanie. Dzięki temu walidacja może nastąpić zgodnie z oczekiwaniami, ale nadal nie jest to rozwiązanie, na które mam nadzieję. Poniższy kod jest praktycznym rozwiązaniem dla tablic. Nadal wymaga, aby rozmiar tablicy był dostarczany do funkcji sprawdzania poprawności, ale jest to łatwe do poprawienia.
#include <initializer_list>
template<typename T>
constexpr bool Compare(T& data, int size, int needleIndex, int haystackIndex)
{
return
needleIndex == haystackIndex ?
Compare(data, size, needleIndex + 1, haystackIndex)
: needleIndex == size ?
false
: data[needleIndex] == data[haystackIndex] ?
true
: Compare(data, size, needleIndex + 1, haystackIndex);
}
template<typename T>
constexpr bool Compare(T& data, int size, int index)
{
return
index == size ?
false
: Compare(data, size, index + 1) ?
true
: Compare(data, size, 0, index);
}
template<typename T, int ArraySize>
constexpr bool Validate(T(&input)[ArraySize], int size)
{
return !Compare(input, size, 0);
}
int main()
{
constexpr int initData0[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
constexpr int initData1[] = {1, 1, 2, 3, 4, 5, 6, 7, 8, 9};
constexpr int initData2[] = {2, 1, 2, 3, 4, 5, 6, 7, 8, 9};
constexpr int initData3[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 8};
constexpr int initData4[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 7};
constexpr int initData5[] = {0, 1, 0, 3, 4, 5, 6, 7, 8, 9};
constexpr int initData6[] = {0, 1, 2, 3, 4, 5, 6, 9, 8, 9};
static_assert(Validate(initData0, 10), "set 0 failed"); // <-- PASS
static_assert(Validate(initData1, 10), "set 1 failed"); // <-- (and below) FAIL
static_assert(Validate(initData2, 10), "set 2 failed");
static_assert(Validate(initData3, 10), "set 3 failed");
static_assert(Validate(initData4, 10), "set 4 failed");
static_assert(Validate(initData5, 10), "set 5 failed");
static_assert(Validate(initData6, 10), "set 6 failed");
}
.
dziennika budowy:
C:\Source\SwitchCaseString\main.cpp: In function 'int main()':
C:\Source\SwitchCaseString\main.cpp:198:2: error: static assertion failed: set 1 failed
C:\Source\SwitchCaseString\main.cpp:199:2: error: static assertion failed: set 2 failed
C:\Source\SwitchCaseString\main.cpp:200:2: error: static assertion failed: set 3 failed
C:\Source\SwitchCaseString\main.cpp:201:2: error: static assertion failed: set 4 failed
C:\Source\SwitchCaseString\main.cpp:202:2: error: static assertion failed: set 5 failed
C:\Source\SwitchCaseString\main.cpp:203:2: error: static assertion failed: set 6 failed
Według obecnego wniosku dotyczącego [C++ 14] (http://isocpp.org/files/papers/N3690.pdf), 'begin()' i ' end() 'of' std :: initializer_list' będzie w przyszłości 'constexpr' (patrz 18.9/1). To usuwa jedną przeszkodę, ale nie jestem pewien, czy usunięcie wartości iteratora kiedykolwiek będzie możliwe podczas kompilacji. – jogojapan
@jogojapan: "Iteratory" z 'std :: initializer_list' są po prostu 'T *' - gwarantowane. –
Xeo
@Xeo Tak, i założyłem, że dereferencja takiego wskaźnika nie będzie dozwolona w stałym wyrażeniu. – jogojapan