#include <boost/variant.hpp>
#include <iostream>
struct Nil {};
auto nil = Nil{};
template <typename T>
struct Cons;
template <typename T>
using List = boost::variant<Nil, boost::recursive_wrapper<Cons<T>>>;
template <typename T>
struct Cons {
Cons( T val, List<T> list ) : head( val ), tail( list ) {}
T head;
List<T> tail;
};
template <typename T>
class length_visitor : public boost::static_visitor<size_t> {
public:
int operator()( Nil ) const {
return 0;
}
int operator()( const Cons<T>& c ) const {
return 1 + length( c.tail );
}
};
template <typename T>
auto cons( T head, List<T> tail ) {
return List<T>( Cons<T>( head, tail ) );
}
template <typename T>
auto cons( T head, Nil ) {
return List<T>( Cons<T>( head, List<T>( Nil{} ) ) );
}
template <typename T>
size_t length( const List<T>& list ) {
return boost::apply_visitor( length_visitor<T>(), list );
}
int main() {
auto l = cons( 3, cons( 2, cons( 1, nil ) ) );
std::cout << length( l ) << std::endl;
return 0;
}
I2luY2x1ZGUgPGJvb3N0L3ZhcmlhbnQuaHBwPgojaW5jbHVkZSA8aW9zdHJlYW0+CgpzdHJ1Y3QgTmlsIHt9OwphdXRvIG5pbCA9IE5pbHt9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIFQ+CnN0cnVjdCBDb25zOwoKdGVtcGxhdGUgPHR5cGVuYW1lIFQ+CnVzaW5nIExpc3QgPSBib29zdDo6dmFyaWFudDxOaWwsIGJvb3N0OjpyZWN1cnNpdmVfd3JhcHBlcjxDb25zPFQ+Pj47Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4Kc3RydWN0IENvbnMgewogIENvbnMoIFQgdmFsLCBMaXN0PFQ+IGxpc3QgKSA6IGhlYWQoIHZhbCApLCB0YWlsKCBsaXN0ICkge30KICAKICBUIGhlYWQ7CiAgTGlzdDxUPiB0YWlsOwp9OwoKdGVtcGxhdGUgPHR5cGVuYW1lIFQ+CmNsYXNzIGxlbmd0aF92aXNpdG9yIDogcHVibGljIGJvb3N0OjpzdGF0aWNfdmlzaXRvcjxzaXplX3Q+IHsKcHVibGljOgogIGludCBvcGVyYXRvcigpKCBOaWwgKSBjb25zdCB7CiAgICByZXR1cm4gMDsKICB9CgogIGludCBvcGVyYXRvcigpKCBjb25zdCBDb25zPFQ+JiBjICkgY29uc3QgewogICAgcmV0dXJuIDEgKyBsZW5ndGgoIGMudGFpbCApOwogIH0KfTsKCnRlbXBsYXRlIDx0eXBlbmFtZSBUPgphdXRvIGNvbnMoIFQgaGVhZCwgTGlzdDxUPiB0YWlsICkgewogIHJldHVybiBMaXN0PFQ+KCBDb25zPFQ+KCBoZWFkLCB0YWlsICkgKTsKfQoKdGVtcGxhdGUgPHR5cGVuYW1lIFQ+CmF1dG8gY29ucyggVCBoZWFkLCBOaWwgKSB7CiAgcmV0dXJuIExpc3Q8VD4oIENvbnM8VD4oIGhlYWQsIExpc3Q8VD4oIE5pbHt9ICkgKSApOwp9Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVD4Kc2l6ZV90IGxlbmd0aCggY29uc3QgTGlzdDxUPiYgbGlzdCApIHsKICByZXR1cm4gYm9vc3Q6OmFwcGx5X3Zpc2l0b3IoIGxlbmd0aF92aXNpdG9yPFQ+KCksIGxpc3QgKTsKfQoKaW50IG1haW4oKSB7CgogIGF1dG8gbCA9IGNvbnMoIDMsIGNvbnMoIDIsIGNvbnMoIDEsIG5pbCApICkgKTsKICBzdGQ6OmNvdXQgPDwgbGVuZ3RoKCBsICkgPDwgc3RkOjplbmRsOwoKICByZXR1cm4gMDsKfQo=