После некоторого копания, похоже, используя std::initializer_list
является не возможно в GCC 4.7 из-за отсутствия constexpr
в его декларации. Он должен работать с GCC 4.8 как <initializer_list>
был обновлен, чтобы включить constexpr
. К сожалению, использование GCC 4.8 на данный момент не является вариантом.
Доступ к элементам массива возможен, если затухающий указатель передается по ссылке. Это позволяет проводить проверку по желанию, но все же это не совсем то решение, на которое я надеюсь. Следующий код является приемлемым решением для массивов. Он по-прежнему требует, чтобы размер массива был передан функции проверки, но его достаточно легко исправить.
#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");
}
.
бревенчатых:
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
Согласно действующему предложению на [C++ 14] (http://isocpp.org/files/papers/N3690.pdf), 'начать()' и ' end() 'из' std :: initializer_list' будет 'constexpr' в будущем (см. 18.9/1). Это устраняет одно препятствие, но я не уверен, будет ли разыменование значений итератора когда-либо во время компиляции. – jogojapan
@jogojapan: «Итераторы» из 'std :: initializer_list' просто «T *» - гарантированы. –
Xeo
@Xeo Да, и я предположил, что разыменование такого указателя не будет разрешено в постоянном выражении. – jogojapan