static_assert 在编译时就知道的索引

sha*_*vey 5 c++ runtime static-assert compile-time c++11

有没有办法对编译时已知的索引进行静态断言,否则运行时断言?例子:

template <class T, int Dim>
class Foo
{
    T _data[Dim];
    public:
        const T &operator[](int idx) const
        {
            static_assert(idx < Dim, "out of range"); // error C2131: expression did not evaluate to a constant
            return _data[idx];
        }
};

int main()
{
    Foo<float, 2> foo;

    foo[0];
    foo[1];
    foo[2]; // compiler error

    for (int i=0; i<5; ++i)
    {
        foo[i]; // run time assert when i > 1
    }

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

max*_*x66 1

我认为用单个函数不可能获得你想要的东西。

即使您开发了一个constexpr函数,我也不认为您能够检测何时执行运行时以及何时执行编译时并以不同的方式执行。

但你可以开发不同的功能。

例如, template get<>(),其中模板参数是索引,只能与编译时已知的索引一起使用,并且可以执行 astatic_assert()和 an at(std::size_t),可以接收在运行时通过运行时检查计算的索引。

顺便说一下:

1) 我建议,像 STL 中通常那样,使用at()来进行绑定检查访问,使用operator[]()来进行绑定未检查访问

2)我建议使用无符号索引,否则您必须检查索引是否为>= 0.

以下是一个工作示例

#include <iostream>
#include <stdexcept>

template <class T, std::size_t Dim>
class Foo
 {
   private:
      T _data[Dim];

   public:
      T const & operator[] (std::size_t idx) const
       { return _data[idx]; }

      template <std::size_t IDX>
      T const & get () const
       {
         static_assert(IDX < Dim, "out of range");

         return this->operator[](IDX);
       }

      T const & at (std::size_t idx) const
       {
         if ( idx >= Dim )
            throw std::range_error("out of range");

         return this->operator[](idx);
       }
 };

int main ()
 {
   Foo<float, 2U> foo;

   foo.get<0U>();
   foo.get<1U>();
   //foo.get<2U>(); // compiler error

   for ( auto i = 0U ; i < 5U ; ++i )
      foo.at(i); // run time exception when i > 1

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