如何在编译时检查查找表是否具有正确的大小?

Dan*_*olf 3 c++

我是查找表的硬编码值.所需数量的元素来自包含的文件,该文件可能在将来的某个时刻发生变化.所以我想在编译时确保我指定的元素数量确实与所需数量匹配.

看看这段代码:

#include <array>

// Assume this comes from some included file
constexpr size_t elementCount = 5;

int main() {
    // This works.
    const std::array<int, elementCount> lookup { 2, 4, 6, 8, 10 };

    // But so does this.
    const std::array<int, elementCount> lookup2 { 2, 4, 6 };

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

std::array看起来非常适合查找表,因为它的大小在编译时是固定的.但是,我无法确保使用正确数量的元素初始化它.由于聚合初始化,即使我指定的元素太少,该示例也会编译正常.

我提出了以下解决方法,但感觉非常难看:

#include <array>

template<class T> std::array<T, 1> makeArray(T e1) {
    return { e1 };
}

template<class T> std::array<T, 2> makeArray(T e1, T e2) {
    return { e1, e2 };
}

template<class T> std::array<T, 3> makeArray(T e1, T e2, T e3) {
    return { e1, e2, e3 };
}

template<class T> std::array<T, 4> makeArray(T e1, T e2, T e3, T e4) {
    return { e1, e2, e3, e4 };
}

template<class T> std::array<T, 5> makeArray(T e1, T e2, T e3, T e4, T e5) {
    return { e1, e2, e3, e4, e5 };
}

// ... and so on; these functions would live in some utility header file.

// Assume this comes from some included file
constexpr size_t elementCount = 5;

int main() {
    // This works.
    const std::array<int, elementCount> lookup = makeArray(2, 4, 6, 8, 10);

    // This doesn't. :-)
    const std::array<int, elementCount> lookup2 = makeArray(2, 4, 6);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

所以问题是:是否有一种优雅的方法可以确保在编译时我为查找表指定正确数量的元素我是硬编码的?注意,数据类型不必是std::array; 任何以常量时间索引的序列容器都可以.

krz*_*zaq 6

你可以模板化你的make_array(类似于make_arrayLibrary Fundamentals TS):

template<typename T, typename... Params>
std::array<T, sizeof...(Params)> make_array(Params&&... ps) {
    return { std::forward<Params>(ps)... };
}
Run Code Online (Sandbox Code Playgroud)

现在,只需创建您的数组:

int main() {
    // This works.
    const auto lookup = makeArray<int>(2, 4, 6, 8, 10);
    static_assert(lookup.size() == elementCount, "");


    // This doesn't. :-)
    const auto lookup2 = makeArray<int>(2, 4, 6);
    static_assert(lookup2.size() == elementCount, ""); // error
}
Run Code Online (Sandbox Code Playgroud)

如果你愿意,你可以将断言移动到你的make_array函数(或为它创建一个包装器),但是,或许,名称更改将按顺序进行:

template<typename T, typename... Params>
std::array<T, sizeof...(Params)> make_lookup_array(Params&&... ps) {
    static_assert(sizeof...(Params) == elementCount, "must be equal!");
    return { std::forward<Params>(ps)... };
}
Run Code Online (Sandbox Code Playgroud)