#include <iostream>
#include <stddef.h> // ptrdiff_t
#include <type_traits> // std::remove_cv
#include <utility> // std::move
#include <vector> // std::vector
typedef ptrdiff_t Size;
template< class Type >
auto movable( Type& o )
-> typename std::remove_cv<Type>::type&&
{
typedef typename std::remove_cv<Type>::type NcvType;
return std::move( const_cast<NcvType&>( o ) );
}
namespace hare {
// A non-copyable array.
template< class Item >
class NcArray
{
private:
NcArray( NcArray const& ); // No such.
NcArray& operator=( NcArray const& ); // No such.
std::vector<Item> items_;
public:
typedef typename std::vector<Item>::const_iterator Iterator;
void append( Item v ) { items_.emplace_back( movable( v ) ); }
auto begin() const -> Iterator { return items_.begin(); }
auto end() const -> Iterator { return items_.end(); }
NcArray(): items_() {}
NcArray( Item const& v )
: items_( v, 1 )
{}
NcArray( NcArray&& other )
: items_( move( other.items_ ) )
{}
};
template< class Item >
inline auto concat( NcArray<Item> a, Item const v )
-> NcArray<Item>
{
a.append( movable( v ) );
return movable( a );
}
} // namespace hare
typedef hare::NcArray<int> Array;
auto collatz_aux( int const n, Array const a )
-> Array
{
if( n == 1 )
{
return concat( movable( a ), 1 );
}
else if( n % 2 == 0 )
{
return collatz_aux( n / 2, concat( movable( a ), n ) );
}
else
{
return collatz_aux( 3 * n + 1, concat( movable( a ), n ) );
}
}
auto collatz( int const n )
-> Array
{
return collatz_aux( n, Array() );
}
auto main()
-> int
{
using namespace std;
for( int const v : collatz( 5 ) )
{
cout << v << " ";
}
cout << endl;
}