使用概念区分一维和二维容器

wim*_*aan 2 c++ containers concept c++23

我想使用概念来区分一维和二维容器。我的第一次尝试如下:

template<typename C>
concept Container1D = requires(C c) {
    std::begin(c);
    std::end(c);
    c[0];
};

template<typename C>
concept Container2D = requires(C c) {
    std::begin(c);
    std::end(c);
    c[0, 0]; // interpreted as comma-operator
};
Run Code Online (Sandbox Code Playgroud)

但显然这不起作用,因为表达式0, 0被解释为逗号运算符,因此第二个概念也匹配一维容器。

有没有办法要求二维operator[a, b]

Jan*_*tke 6

逗号运算符问题

并非每个编译器都支持多维下标运算符。在撰写本文时,编译器支持是这样的

C++23 特性 海湾合作委员会 MSVC
多维下标运算符 12 15 (没有任何)

作为临时解决方法,您可以使用c.operator[](0, 0),只要标准库中存在多维下标重载,它就可以工作,即使尚不支持核心语言功能。

你的概念有问题

通常最好在其他现有concept概念之上构建概念。例如,有std::ranges::range

// in namespace std::ranges
template<typename T>
concept range = requires( T& t ) {
  ranges::begin(t); // equality-preserving for forward iterators
  ranges::end  (t);
};

// building on top of that...
template<typename R>
concept Range1D = std::ranges::range<R> && requires(R& r) {
    { r[0]; } -> std::ranges::range_value_t<R>;
};
Run Code Online (Sandbox Code Playgroud)

然而,这个概念确实很奇怪,因为r[0]意味着您的容器具有随机访问权限,因此使用更强的要求std::ranges::random_access_range会更好:

template<typename R>
concept Range1D = std::ranges::random_access_range<R> && requires(R& r) {
    { r[0]; } -> std::ranges::range_reference_t<R>;
};

template<typename R>
concept Range2D = std::ranges::random_access_range<R> && requires(R& r) {
    { r.operator[](0, 0); } -> std::ranges::range_reference_t<R>;
};
Run Code Online (Sandbox Code Playgroud)