Some people have their custom list class with car
(eg. head) cdr
(eg. tail). I'm wondering if std::list
can be used to support these operations. car
is trivial. But I don't know how cdr
can be emulated.

- 2,043
- 3
- 28
- 45
-
1If you want to modify the list in place, then `pop_front`. If you want to make a copy of the tail portion, then `std::list
{std::next(mylist.begin()), mylist.end()};` – Igor Tandetnik Apr 20 '20 at 14:04 -
2C++ lists don't expose their structure, which is what you would need for "proper" Lisp lists (Newell-Shaw-Simon lists). – molbdnilo Apr 20 '20 at 14:27
-
@IgorTandetnik But `pop_front` lose the orignal list? With lisp `cdr`, the orignal list is still available. – zjk Apr 20 '20 at 14:45
-
Have you read the second part of my comment? – Igor Tandetnik Apr 20 '20 at 15:18
-
2@IgorTandetnik: making a copy of the tail is not what `cdr` does. – Apr 20 '20 at 18:35
-
@tfb maybe by providing a custom allocator it could be possible to share structure – coredump Apr 20 '20 at 19:07
1 Answers
In C++20, we're getting the Ranges library. I haven't looked at it in much detail yet, but I suspect that subranges or views might help here.
Pre C++20
In C++ (up until now), we often don't directly pass a list (or other container) around, but rather a pair of iterators. Take a look at the <algorithm>
library: functions like std::sort
don't take a reference to a container - instead, they take a first
iterator and an last
iterator.
Important: last
does not point to the last item, but rather one place beyond it - the same as std::list::end()
would give you. This means that when first == last
you have "an empty list"
In a pre-C++20 world, you would generally write your code in the same way. One of the advantages of doing this is that if you have a pair of iterators first
and last
, then (as long as first != last
) *first
is the car
, and the pair std::next(first)
and last
is the cdr
. So:
(defun sum (list)
(if (null list)
0
(+ (car list) (sum (cdr list)))))
becomes something like
template <class ForwardIter>
int sum(ForwardIter first, ForwardIter last) {
return (first == last)
? 0
: (*first) + sum(std::next(first), last);
}
(I know some people would disagree with how I've formatted that conditional operator over multiple lines - but I wanted to mirror the Lisp style.)

- 2,375
- 15
- 17