简体   繁体   English

GCC 7.2 C ++ 17 constexpr

[英]Gcc 7.2 c++17 constexpr

I try to implement a constexpr stack only for understand constexpr. 我尝试实现constexpr堆栈只是为了了解constexpr。 I get a compile error from the following code that i don't understand: 我从以下我不理解的代码中得到了一个编译错误:

  1. If I correctly understand constexpr does not imply const 如果我正确理解constexpr并不意味着const
  2. It compiles the init-list constexpr constructor that contains calls to push 它编译包含调用请求的init-list constexpr构造函数。
  3. It compiles the lambda spop that perform a pop 它编译执行流行音乐的lambda流行音乐

What am I missing? 我想念什么?

live example 现场例子

g++ prog.cc -Wall -Wextra -I/opt/wandbox/boost-1.65.0/gcc-7.2.0/include -std=gnu++1z

#include <array>
#include <stdexcept>
#include <type_traits>

namespace ds {
    template <typename T, std::size_t N>
    class array_stack final {
    public:
        using value_type = T;
        using reference = value_type&;
        using const_reference = value_type const&;
        using size_type = std::size_t;

        constexpr bool empty () const
        {
          return items_ == size_type{0};
        }

        constexpr bool full () const
        {
          return top_item_ == N;
        }

        constexpr size_type size () const
        {
          return items_;
        }

        constexpr reference top () &
        {
          if (empty())
            throw std::logic_error{"Attempting top() on empty stack"};

          return array_[top_item_ - 1];
        }

        constexpr const_reference top () const&
        {
          if (empty())
            throw std::logic_error{"Attempting top() on empty stack"};

          return array_[top_item_ - 1];
        }

        constexpr void push (value_type const& value)
        {
          if (full())
            throw std::logic_error{"Attempting push() on full stack"};

          array_[top_item_] = value;
          top_item_++;
          items_++;
        }

        constexpr void push (value_type&& value)
        {
          if (full())
            throw std::logic_error{"Attempting push() on full stack"};

          array_[top_item_] = std::move(value);
          top_item_++;
          items_++;
        }

        constexpr void pop ()
        {
          if (empty())
            throw std::logic_error{"Attempting pop() on empty stack"};

          top_item_--;
          items_--;
        }

        constexpr void clear ()
        {
          items_ = size_type{0};
          top_item_ = size_type{0};
        }

        constexpr array_stack ()
            : items_{size_type{0}}, top_item_{size_type{0}}, array_{}
        {}

        constexpr array_stack (std::initializer_list<value_type> values) : array_stack ()
        {
          for (auto const& v : values)
            push(v);
        }

        constexpr array_stack (array_stack const& rhs) : array_stack ()
        {
          array_ = rhs.array_;
          items_ = rhs.items_;
          top_item_ = rhs.top_item_;
        }

        constexpr array_stack (array_stack&& rhs)
            : items_ {rhs.items_}, top_item_ {rhs.top_item_}, array_ {std::move(rhs.array_)}
        {
          rhs.items_ = size_type{0};
          rhs.top_item_ = size_type{0};
        }

        constexpr array_stack& operator= (array_stack rhs)
        {
          array_ = std::move(rhs.array_);
          items_ = std::move(rhs.items_);
          top_item_ = std::move(rhs.top_item_);
          return *this;
        }

        ~array_stack () = default;

        void swap (array_stack& rhs) noexcept(std::is_nothrow_swappable_v<value_type>)
        {
          using std::swap;
          swap(items_, rhs.items_);
          swap(top_item_, rhs.top_item_);
          swap(array_, rhs.array_);
        }

    private:
        size_type items_;
        size_type top_item_;
        std::array<value_type, N> array_;
    };

    template <typename T, std::size_t N>
    void swap (array_stack<T, N>& lhs, array_stack<T, N>& rhs) noexcept(noexcept(lhs.swap(rhs)))
    {
        lhs.swap(rhs);
    }
}

constexpr bool f()
{
  constexpr ds::array_stack <int, 10> dstack{0,1,2,3,4,5,6,7,8,9};
  constexpr ds::array_stack <int, 10> dstack2{dstack};
  constexpr auto spop =[](auto s){ s.pop(); return s.size(); };
  static_assert(dstack.size() == 10);
  static_assert(!dstack.empty());
  static_assert(dstack.full());
  static_assert(dstack.top() == 9);
  static_assert(dstack2.size() == 10);
  static_assert(spop(dstack) == 9);
  dstack2.pop();
  return true;
}


int main()
{
  constexpr ds::array_stack <int, 10> cstack;
  static_assert(cstack.size() == 0);
  static_assert(cstack.empty());
  static_assert(!cstack.full());

  static_assert(f());

  return 0;
}

I get this error (i understand what it means but why?) 我收到此错误(我理解这是什么意思,但是为什么?)

prog.cc: In function 'constexpr bool f()':
prog.cc:147:15: error: passing 'const ds::array_stack<int, 10>' as 'this' argument discards qualifiers [-fpermissive]
   dstack2.pop();
               ^
prog.cc:66:24: note:   in call to 'constexpr void ds::array_stack<T, N>::pop() [with T = int; long unsigned int N = 10]'
         constexpr void pop ()
                        ^~~
  1. If I correctly understand constexpr does not imply const 如果我正确理解constexpr并不意味着const

No. Objects declared constexpr are indeed const . 否。声明为constexpr对象确实是const That's why dstack2.pop() is ill-formed - the very boring and C++03 reason that you're calling a non- const member function on a const object. 这就是dstack2.pop()的原因-非常无聊且C ++ 03的原因是您要在const对象上调用非const成员函数。

Once you remove the dstack2.pop() line, everything compiles. 删除dstack2.pop()行后,所有内容都会编译。

  1. It compiles the init-list constexpr constructor that contains calls to push 它编译包含调用请求的init-list constexpr构造函数。
  2. It compiles the lambda spop that perform a pop 它编译执行流行音乐的lambda流行音乐

In both of these cases, you're allowed to modify the object. 在这两种情况下,都允许您修改对象。 In the first case, you're still in the constructor - so modifications are fine, the object is never const during construction (otherwise you couldn't construct it). 在第一种情况下,您仍在构造函数中-进行修改就可以了,该对象构造期间永远不会是const (否则无法构造它)。 In the lambda case, the argument isn't const - it's just auto . 在lambda情况下,参数不是const只是auto

[expr.const]/2 : [expr.const] / 2

An expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine, would evaluate one of the following expressions: 表达式e是核心常量表达式,除非按照抽象机的规则对e求值将对以下表达式之一求值:

  • [...] [...]
  • modification of an object unless it is applied to a non-volatile lvalue of literal type that refers to a non-volatile object whose lifetime began within the evaluation of e; 修改对象,除非将其应用于文字类型的非易失性左值,该值是指寿命在e的求值内开始的非易失性对象;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM