c++ - Constexpr 排序的唯一容器集作为数组包装器

标签 c++ arrays constructor set compile-time

我想创建一个像 std::array 这样的 constexpr 容器,它也是经过排序的并且所有元素都是唯一的。我想要实现的是在编译时检查构造函数中给定的数据是否已排序且唯一。我相信 std::set 接口(interface)更接近我想要实现的目标,但它不是 constexpr (还?)。我计划创建一个包装器并在内部使用 std::array,同时在外部公开 std::set 接口(interface)。

当前的实现如下所示

struct ConstexprSet
{
    constexpr ConstexprSet(const std::array<DataType, Size>& data) : mData(data)
    {
        if constexpr (!std::is_sorted(std::cbegin(mData), std::cend(mData)))
            throw std::runtime_error("Data not sorted");
        if constexpr (std::adjacent_find(std::cbegin(mData), std::cend(mData)) != std::cend(mData))
            throw std::runtime_error("Data not unique");
    }
    [[nodiscard]] constexpr auto GetData() const noexcept { return mData; }
private:
    std::array<DataType, Size> mData;
};

我得到的错误是“this”不是常量表达式。如果我使用 data 参数更改 mData,我会发现 data 不是常量表达式。那么到底什么是常量表达式呢? 如果我将整个数组作为 NTTP 传递,这会起作用吗?

所需的用例是这样的

constexpr ConstexprSet features{"A"sv, "B"sv, "C"sv, "D"sv, "E"sv, "F"sv}; 

其中模板参数将从输入参数中推导出来,就像在 std::array 中一样。

以下两个示例不应成功编译,它们应提供全面的消息

constexpr ConstexprSet features{"A"sv, "D"sv, "C"sv, "B"sv, "E"sv, "F"sv}; // Data not sorted
constexpr ConstexprSet features{"A"sv, "B"sv, "B"sv, "D"sv, "E"sv, "F"sv}; // Data not unique

另一个失败的实验是创建一个带有初始化列表的构造函数并将其直接传递到内部数组,但这也不起作用......

任何有关如何克服此问题的想法或我可以遵循的任何其他方法来实现此容器的所需行为将非常受欢迎

我用于实验的当前草稿可以在这里找到 https://godbolt.org/z/1468cEjhW

最佳答案

struct ConstexprSet {
    std::array<DataType, Size> mData;

你不能这样做 - 在类级别,DataTypeSize 甚至没有声明标识符。

让我们声明它们(T 代表 DataTypen 代表 Size):

template<typename T, auto n> class Set {
    std::array<T, n> mData;
// TODO

What I want to achieve is to check at compile time if the given data in the constructor are sorted and unique

那么你需要一个构造函数 consteval (必须在编译时运行),而不是constexpr(运行时/编译时“多态”):

public:
    consteval Set(auto... ts): mData{std::move(ts)...} {
        if (n == 0) return; // can't think of a ready STL algorithm
        for (auto prev = mData.begin(), cur = prev + 1; cur != mData.end(); ++prev, ++cur)
            if (*prev >= *cur)
                throw std::logic_error{"not sorted / not unique"};
    }
};

方便的推演指南:

Set(auto t, auto... ts) -> Set<decltype(t), sizeof...(ts) + 1>;

测试:

int main() {
    constexpr Set set1{"A"sv, "B"sv, "D"sv}; // ok
    constexpr Set set2{"A"sv, "D"sv, "B"sv}; // error
    constexpr Set set3{"A"sv, "D"sv, "D"sv}; // error
}

should give comprehensive messages

source>:24:16: error: constexpr variable 'set2' must be initialized by a constant expression
        constexpr Set set2{"A"sv, "D"sv, "B"sv}; // error
                      ^~~~~~~~~~~~~~~~~~~~~~~~~
<source>:17:5: note: subexpression not valid in a constant expression
                                throw std::logic_error{"not sorted / not unique"};
source>:25:16: error: constexpr variable 'set3' must be initialized by a constant expression
        constexpr Set set3{"A"sv, "D"sv, "D"sv}; // error
                      ^~~~~~~~~~~~~~~~~~~~~~~~~
<source>:17:5: note: subexpression not valid in a constant expression
                                throw std::logic_error{"not sorted / not unique"};

关于c++ - Constexpr 排序的唯一容器集作为数组包装器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69697011/

相关文章:

c++ - ASCII码打印逻辑

java - 从文本文件中获取值并将它们放入数组中

java - 在 Java 中操作类的构造函数

Java封装的Array mutator方法

c++ - 如何在 C++ 代码中搜索所有构造函数?

C++:在原型(prototype)中声明 `auto` 函数返回类型仍然导致在推导错误之前使用 `auto`

c++ - 将 static const char[] 设置为预定义的 static const char[] 失败

python - 在 Python 中重新格式化制表符分隔的数据

复制构造函数的 C++ 辅助函数

java - 编程作业;构造函数 -> 表达式开头无效 + 分号困扰