Line data Source code
1 : // Author(s): Wieger Wesselink, Jan Friso Groote
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 : //
9 :
10 : #ifndef MCRL2_ATERMPP_ATERM_LIST_H
11 : #define MCRL2_ATERMPP_ATERM_LIST_H
12 :
13 : #include "mcrl2/atermpp/detail/aterm_list.h"
14 : #include "mcrl2/atermpp/detail/aterm_list_iterator.h"
15 : #include "mcrl2/atermpp/type_traits.h"
16 :
17 : namespace atermpp
18 : {
19 :
20 : /// \brief A list of aterm objects.
21 : template <typename Term>
22 : class term_list: public aterm
23 : {
24 : protected:
25 : /// \brief Constructor for term lists from internally constructed terms delivered as reference.
26 : explicit term_list(detail::_aterm* t) noexcept :aterm(t)
27 : {
28 : assert(!defined() || type_is_list());
29 : }
30 :
31 : public:
32 : /// The type of object, T stored in the term_list.
33 : typedef Term value_type;
34 :
35 : /// Pointer to T.
36 : typedef Term* pointer;
37 :
38 : /// Reference to T.
39 : typedef Term& reference;
40 :
41 : /// Const reference to T.
42 : typedef const Term& const_reference;
43 :
44 : /// An unsigned integral type.
45 : typedef std::size_t size_type;
46 :
47 : /// A signed integral type.
48 : typedef ptrdiff_t difference_type;
49 :
50 : /// Iterator used to iterate through an term_list.
51 : typedef term_list_iterator<Term> iterator;
52 :
53 : /// Const iterator used to iterate through an term_list.
54 : typedef term_list_iterator<Term> const_iterator;
55 :
56 : /// Const iterator used to iterate through an term_list.
57 : typedef reverse_term_list_iterator<Term> const_reverse_iterator;
58 :
59 : /// \brief Default constructor. Creates an empty list.
60 44108317 : term_list() noexcept
61 44108317 : : aterm(detail::g_term_pool().empty_list())
62 44108317 : {}
63 :
64 : /// \brief Constructor from an aterm.
65 : /// \param t A list.
66 642568389 : explicit term_list(const aterm& t) noexcept
67 642568389 : : aterm(t)
68 : {
69 : // assert(!defined() || type_is_list());
70 642568389 : assert(type_is_list()); // A list should not be a default aterm.
71 642568389 : }
72 :
73 : /// \brief Copy constructor.
74 : /// \param t A list.
75 15651661 : term_list(const term_list<Term>& t) noexcept
76 15651661 : : aterm(t)
77 : {
78 15651661 : assert(!defined() || type_is_list());
79 15651661 : }
80 :
81 : /// \brief Move constructor.
82 : /// \param t A list.
83 1538025 : term_list(term_list<Term>&& t) noexcept
84 1538025 : : aterm(std::move(t))
85 : {
86 1538025 : assert(!defined() || type_is_list());
87 1538025 : }
88 :
89 : /// This class has user-declared copy constructor so declare copy and move assignment.
90 8550652 : term_list& operator=(const term_list& other) noexcept = default;
91 3449665 : term_list& operator=(term_list&& other) noexcept = default;
92 :
93 : /// \brief Creates a term_list with the elements from first to last.
94 : /// \details It is assumed that the range can be traversed from last to first.
95 : /// \param first The start of a range of elements.
96 : /// \param last The end of a range of elements.
97 : template <class Iter>
98 16669682 : explicit term_list(Iter first, Iter last, typename std::enable_if<std::is_base_of<
99 : std::bidirectional_iterator_tag,
100 : typename std::iterator_traits<Iter>::iterator_category
101 : >::value>::type* = nullptr) :
102 : aterm(detail::make_list_backward<Term,Iter,
103 16669682 : detail::do_not_convert_term<Term> >(first, last,detail::do_not_convert_term<Term>()))
104 : {
105 16669682 : assert(!defined() || type_is_list());
106 16669682 : }
107 :
108 : /// \brief Creates a term_list with the elements from first to last converting the elements before inserting.
109 : /// \details It is assumed that the range can be traversed from last to first. The operator () in the class
110 : /// ATermConverter is applied to each element before inserting it in the list.
111 : /// \param first The start of a range of elements.
112 : /// \param last The end of a range of elements.
113 : /// \param convert_to_aterm A class with a () operation, which is applied to each element
114 : /// before it is put into the list.
115 : template <class Iter, class ATermConverter>
116 535 : explicit term_list(Iter first, Iter last, const ATermConverter& convert_to_aterm,
117 : typename std::enable_if<std::is_base_of<
118 : std::bidirectional_iterator_tag,
119 : typename std::iterator_traits<Iter>::iterator_category
120 : >::value>::type* = 0):
121 535 : aterm(detail::make_list_backward<Term,Iter,ATermConverter>(first, last, convert_to_aterm))
122 : {
123 535 : assert(!defined() || type_is_list());
124 535 : }
125 :
126 : /// \brief Creates a term_list with the elements from first to last, converting and filtering the list.
127 : /// \details It is assumed that the range can be traversed from last to first. The operator () in the class
128 : /// ATermConverter is applied to each element before inserting it in the list. Elements are only
129 : /// inserted if the operator () of the class ATermFilter yields true when applied to such an element.
130 : /// \param first The start of a range of elements.
131 : /// \param last The end of a range of elements.
132 : /// \param convert_to_aterm A class with a () operation, which is applied to each element
133 : /// before it is put into the list.
134 : /// \param aterm_filter A class with an operator () that is used to determine whether elements can be inserted in the list.
135 : template <class Iter, class ATermConverter, class ATermFilter>
136 1 : explicit term_list(Iter first, Iter last, const ATermConverter& convert_to_aterm, const ATermFilter& aterm_filter,
137 : typename std::enable_if<std::is_base_of<
138 : std::bidirectional_iterator_tag,
139 : typename std::iterator_traits<Iter>::iterator_category
140 : >::value>::type* = 0):
141 1 : aterm(detail::make_list_backward<Term,Iter,ATermConverter,ATermFilter>(first, last, convert_to_aterm, aterm_filter))
142 : {
143 1 : assert(!defined() || type_is_list());
144 1 : }
145 :
146 : /// \brief Creates a term_list from the elements from first to last.
147 : /// \details The range is traversed from first to last. This requires
148 : /// to copy the elements internally, which is less efficient
149 : /// than this function with random access iterators as arguments.
150 : /// \param first The start of a range of elements.
151 : /// \param last The end of a range of elements.
152 : template <class Iter>
153 2555678 : explicit term_list(Iter first, Iter last,
154 : typename std::enable_if< !std::is_base_of<
155 : std::bidirectional_iterator_tag,
156 : typename std::iterator_traits<Iter>::iterator_category
157 : >::value>::type* = nullptr):
158 : aterm(detail::make_list_forward<Term,Iter,detail::do_not_convert_term<Term> >
159 2555678 : (first, last, detail::do_not_convert_term<Term>()))
160 : {
161 2555678 : assert(!defined() || type_is_list());
162 2555678 : }
163 :
164 : /// \brief Creates a term_list from the elements from first to last converting the elements before inserting.
165 : /// \details The range is traversed from first to last. This requires
166 : /// to copy the elements internally, which is less efficient
167 : /// than this function with random access iterators as arguments.
168 : /// The operator () in the class
169 : /// ATermConverter is applied to each element before inserting it in the list.
170 : /// \param first The start of a range of elements.
171 : /// \param last The end of a range of elements.
172 : /// \param convert_to_aterm A class with a () operation, whic is applied to each element
173 : /// before it is put into the list.
174 : template <class Iter, class ATermConverter>
175 26082 : explicit term_list(Iter first, Iter last, const ATermConverter& convert_to_aterm,
176 : typename std::enable_if< !std::is_base_of<
177 : std::bidirectional_iterator_tag,
178 : typename std::iterator_traits<Iter>::iterator_category
179 : >::value>::type* = nullptr):
180 : aterm(detail::make_list_forward<Term,Iter,ATermConverter>
181 26082 : (first, last, convert_to_aterm))
182 : {
183 26082 : assert(!defined() || type_is_list());
184 26082 : }
185 :
186 : /// \brief Creates a term_list from the elements from first to last converting and filtering the elements before inserting.
187 : /// \details The range is traversed from first to last. This requires
188 : /// to copy the elements internally, which is less efficient
189 : /// than this function with random access iterators as arguments.
190 : /// The operator () in the class ATermConverter is applied to
191 : /// each element before inserting it in the list. Elements are only
192 : /// inserted if the operator () of the class ATermFilter yields true when applied to such an element.
193 : /// \param first The start of a range of elements.
194 : /// \param last The end of a range of elements.
195 : /// \param convert_to_aterm A class with a () operation, whic is applied to each element
196 : /// before it is put into the list.
197 : /// \param aterm_filter A class with an operator () that is used to determine whether elements can be inserted in the list.
198 : template <class Iter, class ATermConverter, class ATermFilter>
199 14 : explicit term_list(Iter first, Iter last, const ATermConverter& convert_to_aterm, const ATermFilter& aterm_filter,
200 : typename std::enable_if< !std::is_base_of<
201 : std::random_access_iterator_tag,
202 : typename std::iterator_traits<Iter>::iterator_category
203 : >::value>::type* = nullptr):
204 : aterm(detail::make_list_forward<Term,Iter,ATermConverter>
205 14 : (first, last, convert_to_aterm, aterm_filter))
206 : {
207 14 : assert(!defined() || type_is_list());
208 14 : }
209 :
210 : /// \brief A constructor based on an initializer list.
211 : /// \details This constructor is not made explicit to conform to initializer lists in standard containers.
212 : /// \param init The initialiser list.
213 9518056 : term_list(std::initializer_list<Term> init)
214 : : aterm(detail::make_list_backward<Term,
215 : typename std::initializer_list<Term>::const_iterator,
216 : detail::do_not_convert_term<Term> >
217 9518056 : (init.begin(), init.end(), detail::do_not_convert_term<Term>()))
218 : {
219 9518056 : assert(!defined() || type_is_list());
220 9518056 : }
221 :
222 : /// \brief Returns the tail of the list.
223 : /// \return The tail of the list.
224 1191404 : const term_list<Term>& tail() const
225 : {
226 1191404 : assert(!empty());
227 1191404 : return (static_cast<const detail::_aterm_list<Term>&>(*m_term)).tail();
228 : }
229 :
230 : /// \brief Removes the first element of the list.
231 213688 : void pop_front()
232 : {
233 213688 : *this = tail();
234 213688 : }
235 :
236 : /// \brief Returns the first element of the list.
237 : /// \return The term at the head of the list.
238 1286719 : const Term& front() const
239 : {
240 1286719 : return static_cast<const detail::_aterm_list<Term>&>(*m_term).head();
241 : }
242 :
243 : /// \brief Inserts a new element at the beginning of the current list.
244 : /// \param el The term that is added.
245 : void push_front(const Term& el);
246 :
247 : /// \brief Construct and insert a new element at the beginning of the current list.
248 : /// \param el The term that is added.
249 : template<typename ...Args>
250 : void emplace_front(Args&&... arguments);
251 :
252 : /// \brief Returns the size of the term_list.
253 : /// \details The complexity of this function is linear in the size of the list.
254 : /// \return The size of the list.
255 621680273 : size_type size() const
256 : {
257 621680273 : std::size_t size=0;
258 1680143606 : for(const_iterator i=begin(); i!=end(); ++i)
259 : {
260 1058463333 : ++size;
261 : }
262 621680273 : return size;
263 : }
264 :
265 : /// \brief Returns true if the list's size is 0.
266 : /// \return True iff the list is empty.
267 4666861 : bool empty() const
268 : {
269 4666861 : return m_term->function() == detail::g_term_pool().as_empty_list();
270 : }
271 :
272 : /// \brief Returns a const_iterator pointing to the beginning of the term_list.
273 : /// \return The beginning of the list.
274 1262706391 : const_iterator begin() const
275 : {
276 1262706391 : return const_iterator(m_term);
277 : }
278 :
279 : /// \brief Returns a const_iterator pointing to the end of the term_list.
280 : /// \return The end of the list.
281 2332820937 : const_iterator end() const
282 : {
283 2332820937 : return const_iterator(detail::address(detail::g_term_pool().empty_list()));
284 : }
285 :
286 : /// \brief Returns a const_reverse_iterator pointing to the end of the term_list.
287 : /// \details This operator requires linear time and memory in the size of the list to yield the iterator.
288 : /// \return The end of the list.
289 2595 : const_reverse_iterator rbegin() const
290 : {
291 2595 : return const_reverse_iterator(m_term);
292 : }
293 :
294 : /// \brief Returns a const_iterator pointing to the end of the term_list.
295 : /// \return The end of the list.
296 5197 : const_reverse_iterator rend() const
297 : {
298 5197 : return const_reverse_iterator();
299 : }
300 :
301 : /// \brief Returns the largest possible size of the term_list.
302 : /// \return The largest possible size of the list.
303 : size_type max_size() const
304 : {
305 : return std::numeric_limits<std::size_t>::max();
306 : }
307 : };
308 :
309 :
310 : /// \brief Make an empty list and put it in target;
311 : /// \param target The variable to which the empty list is assigned.
312 : template <class Term>
313 5454056 : void make_term_list(term_list<Term>& target)
314 : {
315 5454056 : target=atermpp::down_cast<term_list<Term>>(detail::g_term_pool().empty_list());
316 5454056 : }
317 :
318 : /// \brief Creates a term_list with the elements from first to last.
319 : /// \details It is assumed that the range can be traversed from last to first.
320 : /// \param target The variable to which the list is assigned.
321 : /// \param first The start of a range of elements.
322 : /// \param last The end of a range of elements.
323 : template <class Term, class Iter>
324 : void make_term_list(term_list<Term>& target, Iter first, Iter last, typename std::enable_if<std::is_base_of<
325 : std::bidirectional_iterator_tag,
326 : typename std::iterator_traits<Iter>::iterator_category >::value>::type* = nullptr)
327 : {
328 : detail::make_list_backward<Term,Iter,
329 : detail::do_not_convert_term<Term> >(target, first, last,detail::do_not_convert_term<Term>());
330 : assert(!target.defined() || target.type_is_list());
331 : }
332 :
333 : /// \brief Creates a term_list with the elements from first to last converting the elements before inserting.
334 : /// \details It is assumed that the range can be traversed from last to first. The operator () in the class
335 : /// ATermConverter is applied to each element before inserting it in the list.
336 : /// \param target The variable to which the list is assigned.
337 : /// \param first The start of a range of elements.
338 : /// \param last The end of a range of elements.
339 : /// \param convert_to_aterm A class with a () operation, which is applied to each element
340 : /// before it is put into the list.
341 : template <class Term, class Iter, class ATermConverter>
342 : void make_term_list(term_list<Term>& target, Iter first, Iter last, const ATermConverter& convert_to_aterm,
343 : typename std::enable_if<std::is_base_of<
344 : std::bidirectional_iterator_tag,
345 : typename std::iterator_traits<Iter>::iterator_category
346 : >::value>::type* = 0)
347 : {
348 : detail::make_list_backward<Term,Iter,ATermConverter>(target, first, last, convert_to_aterm);
349 : assert(!target.defined() || target.type_is_list());
350 : }
351 :
352 : /// \brief Creates a term_list with the elements from first to last, converting and filtering the list.
353 : /// \details It is assumed that the range can be traversed from last to first. The operator () in the class
354 : /// ATermConverter is applied to each element before inserting it in the list. Elements are only
355 : /// inserted if the operator () of the class ATermFilter yields true when applied to such an element.
356 : /// \param target The variable to which the list is assigned.
357 : /// \param first The start of a range of elements.
358 : /// \param last The end of a range of elements.
359 : /// \param convert_to_aterm A class with a () operation, which is applied to each element
360 : /// before it is put into the list.
361 : /// \param aterm_filter A class with an operator () that is used to determine whether elements can be inserted in the list.
362 : template <class Term, class Iter, class ATermConverter, class ATermFilter>
363 : void make_term_list(term_list<Term>& target, Iter first, Iter last, const ATermConverter& convert_to_aterm, const ATermFilter& aterm_filter,
364 : typename std::enable_if<std::is_base_of<
365 : std::bidirectional_iterator_tag,
366 : typename std::iterator_traits<Iter>::iterator_category
367 : >::value>::type* = 0)
368 : {
369 : detail::make_list_backward<Term,Iter,ATermConverter,ATermFilter>(target, first, last, convert_to_aterm, aterm_filter);
370 : assert(!target.defined() || target.type_is_list());
371 : }
372 :
373 : /// \brief Creates a term_list from the elements from first to last.
374 : /// \details The range is traversed from first to last. This requires
375 : /// to copy the elements internally, which is less efficient
376 : /// than this function with random access iterators as arguments.
377 : /// \param target The variable to which the list is assigned.
378 : /// \param first The start of a range of elements.
379 : /// \param last The end of a range of elements.
380 : template <class Term, class Iter>
381 : void make_term_list(term_list<Term>& target, Iter first, Iter last,
382 : typename std::enable_if< !std::is_base_of<
383 : std::bidirectional_iterator_tag,
384 : typename std::iterator_traits<Iter>::iterator_category
385 : >::value>::type* = nullptr)
386 : {
387 : detail::make_list_forward<Term,Iter,detail::do_not_convert_term<Term> >
388 : (target, first, last, detail::do_not_convert_term<Term>());
389 : assert(!target.defined() || target.type_is_list());
390 : }
391 :
392 : /// \brief Creates a term_list from the elements from first to last converting the elements before inserting.
393 : /// \details The range is traversed from first to last. This requires
394 : /// to copy the elements internally, which is less efficient
395 : /// than this function with random access iterators as arguments.
396 : /// The operator () in the class
397 : /// ATermConverter is applied to each element before inserting it in the list.
398 : /// \param target The variable to which the list is assigned.
399 : /// \param first The start of a range of elements.
400 : /// \param last The end of a range of elements.
401 : /// \param convert_to_aterm A class with a () operation, which is applied to each element
402 : /// before it is put into the list.
403 : template <class Term, class Iter, class ATermConverter>
404 2872296 : void make_term_list(term_list<Term>& target, Iter first, Iter last, const ATermConverter& convert_to_aterm,
405 : typename std::enable_if< !std::is_base_of<
406 : std::bidirectional_iterator_tag,
407 : typename std::iterator_traits<Iter>::iterator_category
408 : >::value>::type* = nullptr)
409 : {
410 : detail::make_list_forward<Term,Iter,ATermConverter>
411 2872296 : (target, first, last, convert_to_aterm);
412 2872296 : assert(!target.defined() || target.type_is_list());
413 2872296 : }
414 :
415 : /// \brief Creates a term_list from the elements from first to last converting and filtering the elements before inserting.
416 : /// \details The range is traversed from first to last. This requires
417 : /// to copy the elements internally, which is less efficient
418 : /// than this function with random access iterators as arguments.
419 : /// The operator () in the class ATermConverter is applied to
420 : /// each element before inserting it in the list. Elements are only
421 : /// inserted if the operator () of the class ATermFilter yields true when applied to such an element.
422 : /// \param target The variable to which the list is assigned.
423 : /// \param first The start of a range of elements.
424 : /// \param last The end of a range of elements.
425 : /// \param convert_to_aterm A class with a () operation, whic is applied to each element
426 : /// before it is put into the list.
427 : /// \param aterm_filter A class with an operator () that is used to determine whether elements can be inserted in the list.
428 : template <class Term, class Iter, class ATermConverter, class ATermFilter>
429 : void make_term_list(term_list<Term>& target, Iter first, Iter last, const ATermConverter& convert_to_aterm, const ATermFilter& aterm_filter,
430 : typename std::enable_if< !std::is_base_of<
431 : std::random_access_iterator_tag,
432 : typename std::iterator_traits<Iter>::iterator_category
433 : >::value>::type* = nullptr)
434 : {
435 : detail::make_list_forward<Term,Iter,ATermConverter>
436 : (target, first, last, convert_to_aterm, aterm_filter);
437 : assert(!target.defined() || target.type_is_list());
438 : }
439 :
440 : /// \brief A constructor based on an initializer list.
441 : /// \details This constructor is not made explicit to conform to initializer lists in standard containers.
442 : /// \param target The variable to which the list is assigned.
443 : /// \param init The initialiser list.
444 : template <class Term>
445 : void make_term_list(term_list<Term>& target, std::initializer_list<Term> init)
446 : {
447 : target=detail::make_list_backward<Term,
448 : typename std::initializer_list<Term>::const_iterator,
449 : detail::do_not_convert_term<Term> >
450 : (init.begin(), init.end(), detail::do_not_convert_term<Term>());
451 : assert(!target.defined() || target.type_is_list());
452 : }
453 :
454 :
455 :
456 : /// \cond INTERNAL_DOCS
457 : namespace detail
458 : {
459 :
460 : /// \brief Template specialization to make a term_list recognizable as a container type (see
461 : /// type_traits.h and detail/type_traits_impl.h).
462 : template < typename T >
463 : struct is_container_impl< atermpp::term_list< T > > : public std::true_type
464 : { };
465 :
466 :
467 : template <class Term>
468 : class _aterm_list : public _aterm_appl<2>
469 : {
470 : public:
471 : /// \returns A reference to the head of the list.
472 1095462939 : const Term& head() const { return static_cast<const Term&>(arg(0)); }
473 :
474 : /// \returns A reference to the tail of the list.
475 2160204987 : const term_list<Term>& tail() const { return static_cast<const term_list<Term>&>(arg(1)); }
476 :
477 2595 : std::size_t size() const
478 : {
479 2595 : std::size_t size=0;
480 2595 : for(_aterm_list const* i=this;
481 5197 : i->function()!=detail::g_term_pool().as_empty_list();
482 2602 : i=static_cast<_aterm_list const*>(address(i->tail())))
483 : {
484 2602 : ++size;
485 : }
486 2595 : return size;
487 : }
488 :
489 : };
490 :
491 : } // namespace detail
492 : /// \endcond
493 :
494 :
495 : /// \brief A term_list with elements of type aterm.
496 : typedef term_list<aterm> aterm_list;
497 :
498 :
499 : /// \brief Returns the list with the elements in reversed order.
500 : /// \param l A list.
501 : /// \details This operator is linear in the size of the list.
502 : /// \return The reversed list.
503 : template <typename Term>
504 : inline
505 : term_list<Term> reverse(const term_list<Term>& l);
506 :
507 : /// \brief Returns the list with the elements sorted according to the <-operator on the addresses of terms.
508 : /// \param l A list.
509 : /// \param ordering An total orderings relation on Term, by default the ordering relation on Terms.
510 : /// \details This operator has complexity nlog n where n is the size of the list.
511 : /// \return The sorted list.
512 : template <typename Term>
513 : inline
514 : term_list<Term> sort_list(const term_list<Term>& l,
515 : const std::function<bool(const Term&, const Term&)>& ordering
516 18 : = [](const Term& t1, const Term& t2){ return t1<t2;});
517 :
518 :
519 : /// \brief Returns the concatenation of two lists with convertible element types.
520 : /// \details The type of the result is either the type of l, if the elements of m
521 : /// can be converted implicitly to the type of the elements of l. Otherwise if the
522 : /// elements of l can be converted implicitly to the type of the elements
523 : /// of m, the result type is that or m.
524 : /// \param l A list.
525 : /// \param m A list.
526 : /// \details The complexity of this operator is linear in the length of l.
527 : /// \return The concatenation of the lists l followed by m.
528 :
529 : template <typename Term1, typename Term2>
530 : inline
531 : typename std::conditional<std::is_convertible<Term2,Term1>::value,term_list<Term1>,term_list<Term2>>::type
532 : operator+(const term_list<Term1>& l, const term_list<Term2>& m);
533 :
534 :
535 : /// \brief Appends a new element at the end of the list. Note
536 : /// that the complexity of this function is O(n), with n the number of
537 : /// elements in the list!!!
538 : /// \param l The list to which the term is appended.
539 : /// \param el A term.
540 : /// \return The list l with elem appended at the end.
541 : template <typename Term>
542 : inline
543 : term_list<Term> push_back(const term_list<Term>& l, const Term& el);
544 :
545 : /// \brief Converts the given term list to a vector.
546 : template <typename T>
547 : std::vector<T> as_vector(const atermpp::term_list<T>& x)
548 : {
549 : return std::vector<T>(x.begin(), x.end());
550 : }
551 :
552 : /// \brief Converts the given term list to a set.
553 : template <typename T>
554 : std::set<T> as_set(const atermpp::term_list<T>& x)
555 : {
556 : return std::set<T>(x.begin(), x.end());
557 : }
558 :
559 : } // namespace atermpp
560 :
561 :
562 : namespace std
563 : {
564 : //
565 : /// \brief Swaps two term_lists.
566 : /// \details This operation is more efficient than exchanging terms by an assignment,
567 : /// as swapping does not require to change the protection of terms.
568 : /// \param t1 The first term
569 : /// \param t2 The second term
570 : template <class T>
571 1153 : inline void swap(atermpp::term_list<T>& t1, atermpp::term_list<T>& t2) noexcept
572 : {
573 1153 : t1.swap(t2);
574 1153 : }
575 :
576 : /// \brief The standard hash class.
577 : template <class Term>
578 : struct hash<atermpp::term_list<Term> >
579 : {
580 : /// \brief A specialization of the standard std::hash function.
581 : /// \param l The list for which a hash value is calculated.
582 : /// \return A hash value for l.
583 : std::size_t operator()(const atermpp::term_list<Term>& l) const
584 : {
585 : std::hash<atermpp::aterm> hasher;
586 : return hasher(l);
587 : }
588 : };
589 :
590 : } // namespace std
591 :
592 : #include "mcrl2/atermpp/detail/aterm_list_implementation.h"
593 :
594 : #endif // MCRL2_ATERMPP_ATERM_LIST_H
|