Je tente d'implémenter une pile constexpr uniquement pour comprendre constexpr. je reçois une erreur de compilation du code ci-dessous que je ne comprends pas:Gcc 7.2 C++ 17 constexpr
- Si je comprends bien constexpr ne signifie pas const
- Il compile le constructeur constexpr liste d'initialisation qui contient des appels à pousser
- Il compile le spop lambda qui effectue une pop
Que manque-t-il?
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;
}
Je reçois cette erreur (je comprends ce que cela signifie, mais pourquoi?)
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()
^~~
Merci pour vos explications, mais je ne le point unserstand 3. Il est objet constexpr qu'il est modifié de sorte je n'obtenir le ce qui est différent. de toute façon +1 – Genxers
@Genxers, vérifiez 'dstack.size()' à la fin.Votre lambda modifie une * copie *. – rustyx
@RustyX oui c'est sûr mais c'est fait au moment de la compilation comme vous pouvez le voir sur static_assert. Est-ce un comportement que je ne comprends pas. – Genxers