c++ - 在编译时验证 std::initializer_list 的内容

标签 c++ validation c++11 initializer-list constexpr

我试图在编译时确定 std::initializer_list 中的所有值是否都是唯一的。我能够找到 valiate the size 的解决方案的列表,但无法将其应用于内容。我尝试过使用自由函数和构造函数,但这两种方法都导致 GCC 4.7.2 出现以下错误。

error: non-constant condition for static assertion
error: 'begin' is not a constant expression

我意识到 std::initializer_list 的成员没有被声明为 constexpr 但我希望有一个像大小验证这样的解决方案。是否可以在编译时使用类似以下内容验证内容?

#include <initializer_list>

template<typename InputIterator>
constexpr bool Validate(InputIterator begin, InputIterator end)
{
    static_assert(*begin == *end, "begin and end are the same");
    //  The actual implemetnation is a single line recursive check.
    return true;
}

template<typename InputType>
constexpr bool Validate(const std::initializer_list<InputType>& input)
{
    // "-1" removed to simplify and eliminate potential cause of error
    return Validate(input.begin(), input.end() /* - 1 */);
}

int main()
{
    Validate({1, 2, 1});
}

最佳答案

经过一些挖掘,它看起来像使用 std::initializer_list由于缺少 constexpr,在 GCC 4.7 中不可能在它的声明中。它应该与 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++ - 在编译时验证 std::initializer_list 的内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16746564/

相关文章:

c# - 至少应通过 asp.net mvc 中的自定义验证检查一个单选按钮

asp.net-mvc-3 - 如何实现 MVC3 模型 URL 验证?

c++ - GCC 优化基于固定范围的 for 循环,就好像它有更长的可变长度一样

c++ - 为什么在这种情况下创建临时实例不起作用?

c++ - 一个类中的多个可能的模板

c++ - 删除 map 的最后 5 个元素

ios - 在 iOS 中用于密码验证的 UITextfield 输入中的密码验证

c++ - ostream& operator<< 令人费解的编译错误的显式模板参数规范

c++ - 将结构转换为 char* 并返回

c++ - 发送 MAPI 消息时遇到问题