代码之家  ›  专栏  ›  技术社区  ›  Adam Barnes

我如何定义一个基于constexpr函数返回值进行限制的概念?

  •  1
  • Adam Barnes  · 技术社区  · 4 月前

    假设我想写一个函数,接受任何我可以迭代的东西,大小为 2 。我该如何写一个概念来做到这一点?我认为我得到的最接近的结果如下:

    #include <array>
    #include <concepts>
    #include <iostream>
    #include <ranges>
    
    template<typename T, size_t N>
    concept RangeOfSize =
      std::ranges::sized_range<T> &&
      requires (T i) { i.size() == N; }
    ;
    
    void f(RangeOfSize<2> auto&& r) { std::cout << r.size() << std::endl; }
    
    int main() {
        f(std::array<uint8_t, 2>{2, 3});
        f(std::array<uint8_t, 3>{5, 7, 11});
    }
    

    g++ -std=c++23 $0 -o exe -Wall -Werror -Wextra -pedantic-errors

    令我懊恼的是,它编译得很好,输出也很好

    2
    3
    

    理想情况下,它在第二次调用时无法编译 f 因为该数组不是2个元素长。非常理想的情况是,它会因为一个易读的错误而失败,但我对此放弃了希望。

    (关于我自己是如何得出答案的解释的加分)。

    1 回复  |  直到 4 月前
        1
  •  2
  •   NathanOliver    4 月前

    你可以只使用 static_assert 为了实现这一点:

    void f(auto&& r) 
    { 
        static_assert(r.size() == 2, "Only ranges of size 2 supported");
        std::cout << r.size() << std::endl; 
    }
    

    For

    f(std::array<int, 3>{5, 7, 11});
    

    GCC给出以下输出:

    <source>: In instantiation of 'void f(auto:10&&) [with auto:10 = std::array<int, 3>]':
    <source>:18:6:   required from here
       18 |     f(std::array<int, 3>{5, 7, 11});
          |     ~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    <source>:12:28: error: static assertion failed: Only ranges of size 2 supported
       12 |     static_assert(r.size() == 2, "Only ranges of size 2 supported");
          |                   ~~~~~~~~~^~~~
    <source>:12:28: note: the comparison reduces to '(3 == 2)'
    Compiler returned: 1