mCRL2
Loading...
Searching...
No Matches
aterm.h
Go to the documentation of this file.
1// Author(s): Wieger Wesselink
2// Copyright: see the accompanying file COPYING or copy at
3// https://github.com/mCRL2org/mCRL2/blob/master/COPYING
4//
5// Distributed under the Boost Software License, Version 1.0.
6// (See accompanying file LICENSE_1_0.txt or copy at
7// http://www.boost.org/LICENSE_1_0.txt)
8//
11
12#ifndef MCRL2_ATERMPP_ATERM_APPL_H
13#define MCRL2_ATERMPP_ATERM_APPL_H
14
20
21namespace atermpp
22{
23
24class aterm: public aterm_core
25{
26protected:
31 : aterm_core(reinterpret_cast<detail::_aterm*>(t))
32 {}
33
34public:
36 typedef std::size_t size_type;
37
39 typedef ptrdiff_t difference_type;
40
43
46
49 {}
50
51 /* /// \brief Explicit constructor from an aterm_core.
53 explicit aterm(const aterm_core& t)
54 : aterm_core(t)
55 {} */
56
58 aterm(const aterm& other) noexcept = default;
59 aterm& operator=(const aterm& other) noexcept = default;
60 aterm(aterm&& other) noexcept = default;
61 aterm& operator=(aterm&& other) noexcept = default;
62
71 template <class ForwardIterator,
72 typename std::enable_if<mcrl2::utilities::is_iterator<ForwardIterator>::value>::type* = nullptr,
73 typename std::enable_if<!std::is_same<typename ForwardIterator::iterator_category, std::input_iterator_tag>::value>::type* = nullptr,
74 typename std::enable_if<!std::is_same<typename ForwardIterator::iterator_category, std::output_iterator_tag>::value>::type* = nullptr>
76 ForwardIterator begin,
77 ForwardIterator end)
78 {
80 static_assert(!std::is_same<typename ForwardIterator::iterator_category, std::input_iterator_tag>::value,
81 "A forward iterator has more requirements than an input iterator.");
82 static_assert(!std::is_same<typename ForwardIterator::iterator_category, std::output_iterator_tag>::value,
83 "A forward iterator has more requirements than an output iterator.");
84 }
85
93 template <class InputIterator,
94 typename std::enable_if<mcrl2::utilities::is_iterator<InputIterator>::value>::type* = nullptr,
95 typename std::enable_if<std::is_same<typename InputIterator::iterator_category, std::input_iterator_tag>::value>::type* = nullptr>
97 InputIterator begin,
98 InputIterator end)
99 : aterm(sym, begin, end, [](const unprotected_aterm_core& term) -> const unprotected_aterm_core& { return term; } )
100 {
101 static_assert(std::is_same<typename InputIterator::iterator_category, std::input_iterator_tag>::value,
102 "The InputIterator is missing the input iterator tag.");
103 }
104
113 template <class InputIterator,
114 class TermConverter,
115 typename std::enable_if<mcrl2::utilities::is_iterator<InputIterator>::value>::type* = nullptr>
117 InputIterator begin,
118 InputIterator end,
119 TermConverter converter)
120 {
121 detail::g_thread_term_pool().create_appl_dynamic(*this, sym, converter, begin, end);
122 static_assert(!std::is_same<typename InputIterator::iterator_category, std::output_iterator_tag>::value,
123 "The InputIterator has the output iterator tag.");
124 }
125
129 {
131 }
132
136 template<typename ...Terms>
137 aterm(const function_symbol& symbol, const Terms& ...arguments)
138 {
139 detail::g_thread_term_pool().create_appl(*this, symbol, arguments...);
140 }
141
145 {
146 return m_term->function();
147 }
148
152 {
153 return m_term->function().arity();
154 }
155
158 bool empty() const
159 {
160 return size()==0;
161 }
162
166 {
167 return const_iterator(&static_cast<const aterm&>(reinterpret_cast<const detail::_term_appl*>(m_term)->arg(0)));
168 }
169
173 {
174 return const_iterator(&static_cast<const aterm&>(reinterpret_cast<const detail::_term_appl*>(m_term)->arg(size())));
175 }
176
179 constexpr size_type max_size() const
180 {
181 return std::numeric_limits<size_type>::max();
182 }
183
187 const aterm& operator[](const size_type i) const
188 {
189 assert(i < size()); // Check the bounds.
190 return static_cast<const aterm&>(reinterpret_cast<const detail::_term_appl*>(m_term)->arg(i));
191 }
192};
193
194typedef void(*term_callback)(const aterm&);
195
197
198
208template <class Term,
209 class ForwardIterator,
210 typename std::enable_if<mcrl2::utilities::is_iterator<ForwardIterator>::value>::type* = nullptr,
211 typename std::enable_if<!std::is_same<typename ForwardIterator::iterator_category, std::input_iterator_tag>::value>::type* = nullptr,
212 typename std::enable_if<!std::is_same<typename ForwardIterator::iterator_category, std::output_iterator_tag>::value>::type* = nullptr>
213void make_term_appl(Term& target,
214 const function_symbol& sym,
215 ForwardIterator begin,
216 ForwardIterator end)
217{
218 detail::g_thread_term_pool().create_appl_dynamic(target, sym, begin, end);
219
220 static_assert((std::is_base_of<aterm, Term>::value),"Term must be derived from an aterm");
221 static_assert(sizeof(Term)==sizeof(std::size_t),"Term derived from an aterm must not have extra fields");
222 static_assert(!std::is_same<typename ForwardIterator::iterator_category, std::input_iterator_tag>::value,
223 "A forward iterator has more requirements than an input iterator.");
224 static_assert(!std::is_same<typename ForwardIterator::iterator_category, std::output_iterator_tag>::value,
225 "A forward iterator has more requirements than an output iterator.");
226}
227
228
237template <class Term,
238 class InputIterator,
239 typename std::enable_if<mcrl2::utilities::is_iterator<InputIterator>::value>::type* = nullptr,
240 typename std::enable_if<std::is_same<typename InputIterator::iterator_category, std::input_iterator_tag>::value>::type* = nullptr>
241void make_term_appl(Term& target,
242 const function_symbol& sym,
243 InputIterator begin,
244 InputIterator end)
245{
246 make_term_appl(target, sym, begin, end, [](const Term& term) -> const Term& { return term; } );
247
248 static_assert((std::is_base_of<aterm, Term>::value),"Term must be derived from an aterm");
249 static_assert(sizeof(Term)==sizeof(std::size_t),"Term derived from an aterm must not have extra fields");
250 static_assert(std::is_same<typename InputIterator::iterator_category, std::input_iterator_tag>::value,
251 "The InputIterator is missing the input iterator tag.");
252}
253
264template <class Term,
265 class InputIterator,
266 class TermConverter,
267 typename std::enable_if<mcrl2::utilities::is_iterator<InputIterator>::value>::type* = nullptr>
268void make_term_appl(Term& target,
269 const function_symbol& sym,
270 InputIterator begin,
271 InputIterator end,
272 TermConverter converter)
273{
274 detail::g_thread_term_pool().create_appl_dynamic(target, sym, converter, begin, end);
275
276 static_assert(std::is_base_of<aterm, Term>::value,"Term must be derived from an aterm");
277 static_assert(sizeof(Term)==sizeof(std::size_t),"Term derived from an aterm must not have extra fields");
278 static_assert(!std::is_same<typename InputIterator::iterator_category, std::output_iterator_tag>::value,
279 "The InputIterator has the output iterator tag.");
280}
281
285template <class Term>
286void make_term_appl(Term& target,
287 const function_symbol& sym)
288{
290
291 static_assert(std::is_base_of<aterm, Term>::value,"Term must be derived from an aterm");
292 static_assert(sizeof(Term)==sizeof(std::size_t),"Term derived from an aterm must not have extra fields");
293}
294
299template<class Term,
300 typename ...Terms>
301void make_term_appl(Term& target, const function_symbol& symbol, const Terms& ...arguments)
302{
303 detail::g_thread_term_pool().create_appl(target, symbol, arguments...);
304}
305
310template<class Term,
311 class INDEX_TYPE,
312 typename ...Terms>
313void make_term_appl_with_index(aterm& target, const function_symbol& symbol, const Terms& ...arguments)
314{
315 detail::g_thread_term_pool().create_appl_index<Term, INDEX_TYPE>(target, symbol, arguments...);
316}
317
318template <class Term1, class Term2>
319struct is_convertible : public
320 std::conditional<std::is_base_of<aterm, Term1>::value &&
321 std::is_base_of<aterm, Term2>::value && (
322 std::is_convertible<Term1, Term2>::value ||
323 std::is_convertible<Term2, Term1>::value),
324 std::true_type, std::false_type>::type
325{ };
326
336template <class Derived, class Base>
337const Derived& down_cast(const Base& t,
338 typename std::enable_if<is_convertible<Base, Derived>::value &&
339 !std::is_base_of<Derived, Base>::value>::type* = nullptr)
340{
341 static_assert(sizeof(Derived) == sizeof(aterm),
342 "aterm cast can only be applied ot types derived from aterms where no extra fields are added");
343 assert(Derived(static_cast<const aterm&>(t)) != aterm());
344 return reinterpret_cast<const Derived&>(t);
345}
346
348// This can be useful when assigning to a term type that contains the derived term type.
351template <class Derived, class Base>
352Derived& reference_cast(Base& t,
353 typename std::enable_if<is_convertible<Base, Derived>::value &&
354 !std::is_base_of<Derived, Base>::value >::type* = nullptr)
355{
356 static_assert(sizeof(Base) == sizeof(aterm),
357 "aterm cast can only be applied to terms directly derived from aterms");
358 static_assert(sizeof(Derived) == sizeof(aterm),
359 "aterm cast can only be applied to types derived from aterms where no extra fields are added");
360 // We do not check types as the content of the term t is likely to be overwritten shortly.
361 return reinterpret_cast<Derived&>(t);
362}
363
365// This can be useful when assigning to a term type that contains the derived term type.
366// In case Derived and Base are equal, nothing needs to be done.
369template <class Derived>
370Derived& reference_cast(Derived& t)
371{
372 static_assert(sizeof(Derived) == sizeof(aterm),
373 "aterm cast can only be applied to terms directly derived from aterms");
374 // We do not check types as the content of the term t is likely to be overwritten shortly.
375 return t;
376}
377
378template < typename DerivedCont, typename Base, template <typename Elem> class Cont >
379const DerivedCont& container_cast(const Cont<Base>& t,
380 typename std::enable_if_t<
382 std::is_same_v<Cont<typename DerivedCont::value_type>, DerivedCont> &&
383 !std::is_base_of_v<DerivedCont, Cont<Base> > &&
385 >* = nullptr)
386{
387 static_assert(sizeof(typename DerivedCont::value_type) == sizeof(aterm),
388 "aterm cast cannot be applied types derived from aterms where extra fields are added");
389 assert(std::all_of(t.begin(),t.end(),[](const Base& u){ return typename DerivedCont::value_type(static_cast<const aterm&>(u)) != aterm();} ));
390 return reinterpret_cast<const DerivedCont&>(t);
391}
392
398template <class Derived, class Base>
399const Derived& vertical_cast(const Base& t,
400 typename std::enable_if<is_convertible<Base, Derived>::value>::type* = nullptr)
401{
402 static_assert(sizeof(Derived) == sizeof(aterm),
403 "aterm cast cannot be applied types derived from aterms where extra fields are added");
404 assert(Derived(static_cast<const aterm&>(t)) != aterm());
405 return reinterpret_cast<const Derived&>(t);
406}
407
408template < typename DerivedCont, typename Base, template <typename Elem> class Cont >
409const DerivedCont& vertical_cast(const Cont<Base>& t,
410 typename std::enable_if_t<
412 std::is_same_v<Cont<typename DerivedCont::value_type>, DerivedCont> &&
414 >* = nullptr)
415{
416 static_assert(sizeof(typename DerivedCont::value_type) == sizeof(aterm),
417 "aterm cast cannot be applied types derived from aterms where extra fields are added");
418 assert(std::all_of(t.begin(),t.end(),[](const Base& u){ return typename DerivedCont::value_type(static_cast<const aterm&>(u)) != aterm();} ));
419 return reinterpret_cast<const DerivedCont&>(t);
420}
421
422/* namespace detail
423{
425 inline _aterm* address(const unprotected_aterm_core& t)
426 {
427 return const_cast<_aterm*>(t.m_term);
428 }
429} */
430
435std::ostream& operator<<(std::ostream& out, const atermpp::aterm& t);
436
440inline std::string pp(const atermpp::aterm& t)
441{
442 std::ostringstream oss;
443 oss << t;
444 return oss.str();
445}
446
447} // namespace atermpp
448
449namespace std
450{
451
461template <>
463{
464 t1.swap(t2);
465}
466} // namespace std
467namespace std
468{
469
475inline void swap(atermpp::aterm& t1, atermpp::aterm& t2) noexcept
476{
477 t1.swap(t2);
478}
479
481template<> struct hash<atermpp::aterm>
482{
483 std::size_t operator()(const atermpp::aterm& t) const
484 {
485 return std::hash<atermpp::aterm_core>()(t);
486 }
487};
488
489} // namespace std
490
491#endif // MCRL2_ATERMPP_ATERM_APPL_H
The aterm_core base class that provides protection of the underlying shared terms.
Definition aterm_core.h:182
aterm(aterm &&other) noexcept=default
aterm(const function_symbol &sym, InputIterator begin, InputIterator end, TermConverter converter)
Definition aterm.h:116
const_iterator end() const
Returns a const_iterator pointing past the last argument.
Definition aterm.h:172
aterm(const function_symbol &symbol, const Terms &...arguments)
Constructor for n-arity function application.
Definition aterm.h:137
const aterm & operator[](const size_type i) const
Returns the i-th argument.
Definition aterm.h:187
aterm()
Default constructor.
Definition aterm.h:48
const_iterator begin() const
Returns an iterator pointing to the first argument.
Definition aterm.h:165
aterm(const function_symbol &sym, InputIterator begin, InputIterator end)
Constructor that provides an aterm based on a function symbol and an input iterator providing the arg...
Definition aterm.h:96
aterm(const function_symbol &sym, ForwardIterator begin, ForwardIterator end)
Constructor that provides an aterm based on a function symbol and forward iterator providing the argu...
Definition aterm.h:75
aterm & operator=(const aterm &other) noexcept=default
const function_symbol & function() const
Returns the function symbol belonging to an aterm.
Definition aterm.h:144
std::size_t size_type
An unsigned integral type.
Definition aterm.h:36
aterm(const aterm &other) noexcept=default
This class has user-declared copy constructor so declare default copy and move operators.
aterm(detail::_term_appl *t)
Constructor.
Definition aterm.h:30
ptrdiff_t difference_type
A signed integral type.
Definition aterm.h:39
bool empty() const
Returns true if the term has no arguments.
Definition aterm.h:158
aterm & operator=(aterm &&other) noexcept=default
aterm(const function_symbol &sym)
Constructor.
Definition aterm.h:128
term_appl_iterator< aterm > iterator
Iterator used to iterate through an term_appl.
Definition aterm.h:42
size_type size() const
Returns the number of arguments of this term.
Definition aterm.h:151
term_appl_iterator< aterm > const_iterator
Const iterator used to iterate through an term_appl.
Definition aterm.h:45
constexpr size_type max_size() const
Returns the largest possible number of arguments.
Definition aterm.h:179
This class stores a term followed by N arguments. Where N should be equal to the arity of the functio...
Definition aterm.h:34
const function_symbol & function() const noexcept
Definition aterm_core.h:55
void create_appl(aterm &term, const function_symbol &sym, const Terms &... arguments)
void create_term(aterm &term, const function_symbol &sym)
void create_appl_dynamic(aterm &term, const function_symbol &sym, ForwardIterator begin, ForwardIterator end)
void create_appl_index(aterm &term, const function_symbol &sym, const Terms &... arguments)
std::size_t arity() const
Return the arity (number of arguments) of the function symbol (function_symbol).
Iterator for term_appl.
An unprotected term does not change the reference count of the shared term when it is copied or moved...
Definition aterm_core.h:32
const detail::_aterm * m_term
Definition aterm_core.h:36
thread_aterm_pool & g_thread_term_pool()
A reference to the thread local term pool storage.
The main namespace for the aterm++ library.
Definition algorithm.h:21
void(* term_callback)(const aterm &)
Definition aterm.h:194
std::string pp(const atermpp::aterm &t)
Transform an aterm to an ascii string.
Definition aterm.h:440
std::ostream & operator<<(std::ostream &out, const atermpp::aterm &t)
Send the term in textual form to the ostream.
void make_term_appl(Term &target, const function_symbol &sym, ForwardIterator begin, ForwardIterator end)
Constructor an aterm in a variable based on a function symbol and an forward iterator providing the a...
Definition aterm.h:213
void add_deletion_hook(const function_symbol &, term_callback)
Check for reasonably sized aterm (32 bits, 4 bytes) This check might break on perfectly valid archite...
const DerivedCont & container_cast(const Cont< Base > &t, typename std::enable_if_t< is_container< DerivedCont, aterm >::value &&std::is_same_v< Cont< typename DerivedCont::value_type >, DerivedCont > &&!std::is_base_of_v< DerivedCont, Cont< Base > > &&is_convertible< Base, typename DerivedCont::value_type >::value > *=nullptr)
Definition aterm.h:379
void make_term_appl_with_index(aterm &target, const function_symbol &symbol, const Terms &...arguments)
Constructor for n-arity function application with an index.
Definition aterm.h:313
const Derived & vertical_cast(const Base &t, typename std::enable_if< is_convertible< Base, Derived >::value >::type *=nullptr)
A cast form an aterm derived class to a class that inherits in possibly multiple steps from this clas...
Definition aterm.h:399
const Derived & down_cast(const Base &t, typename std::enable_if< is_convertible< Base, Derived >::value &&!std::is_base_of< Derived, Base >::value >::type *=nullptr)
A cheap cast from one aterm based type to another When casting one aterm based type into another,...
Definition aterm.h:337
Derived & reference_cast(Base &t, typename std::enable_if< is_convertible< Base, Derived >::value &&!std::is_base_of< Derived, Base >::value >::type *=nullptr)
A cast from one aterm based type to another, as a reference, allowing to assign to it.
Definition aterm.h:352
STL namespace.
void swap(atermpp::unprotected_aterm_core &t1, atermpp::unprotected_aterm_core &t2) noexcept
Swaps two aterms.
Definition aterm.h:462
std::size_t operator()(const atermpp::aterm &t) const
Definition aterm.h:483
#define hash(l, r, m)
Definition tree_set.cpp:23