learn from the following codes, and provide a Markdown introduction:
```cpp
#include"meta_object_traits.hpp"

//this file is a demonstration of how to metaprogramming with meta_object

using namespace meta_typelist;//this namespace contains facilities like meta_looper, meta_stream
using namespace list_common_object;//namespace contains templates for fast meta_object generators

//meta_looper
//a meta_looper is a compile-time looping facilities, it controls the looping by three template arguments
//all template arguments are meta_object, it requires, a meta_conditional object, a meta_object, 
//a meta_generate object, here is an example

using TL = meta_looper_t 
<
    meta_length_limiter_o<5>,//this is a condition object that limits the length of the list in meta_object 
    meta_appendable_o<exp_list<int, int, int>>,//this meta object accepts any types from the generator to the target list
    meta_ret_decreasible_o<exp_list<int, int, int, int>>//this is a generator object, with each loop, it reduce itself by one type in the list, and return the type to the meta object that is being handling
>::type;//TL = exp_list<int, int, int, int, int>

//the generator object is not must, if not provided, it defaults being a meta_empty_o, it provide a dummy type without affecting the handling meta object
//using meta_empty_o = meta_object<meta_empty, meta_empty_fn>

//how to define a customized meta_object
//meta_object is a Type, binding with a meta_function, there are 3 types of meta_object

//meta_object function, here, we showcase the meta_appendable_o, it is in namespace meta_traits::common_object
struct meta_append_example {//
    template<class thisTL,//this is the typelist stored in meta_object, it updates each time when invoked
        class T//this is the type sent by the generator
    >
    using apply =//the meta object requires you use this name 'apply' to be invoked as a nested template class, it must have at least two template arguments
        meta_invoke<common_object::append, thisTL, T>;//here we simply append the type to the thisList
};

//finally, define the meta object template
//the TL is updated in each looping, it will be sent to the condition object, to determin if the looping should be continue
template<class TL> using meta_append_example_o = meta_object<TL, meta_append_example>;

//meta_ret_object
//the meta_ret_object is a meta_object that has a return value while as performing its own transformation,
//a meta_ret_object normally is a meta generator object, but it could also serve as a handling object, to define a meta_ret_object
//besides meta handling function, you must provide a ret_function
struct meta_ret_example {
    template<class thisTL>//this is the typelist stored in meta_ret_object
    using apply = exp_select<max_index<thisTL>, thisTL>;//here, we return the final type in type list each looping
};
//meta_object is flexible, we can combine the previous meta_object function
template<class TL> using meta_ret_last_o = meta_ret_object<TL, meta_append_example, meta_ret_example>;
//so what have we here, this meta ret object repletely accept types to its stored list, and return the last type to other objects

//now we need to define a condition object
template<class T>
struct stop_at_type {
    template<class ThisType, class ...>
    struct apply
    {
        const static bool value = !std::is_same_v<ThisType, T>;
    };
};

//now our loop stops when ThisTL has a double in the tail, according to our logic
template<class T, class TL>
using cut_at_type = meta_looper_t<meta_condition_c_o<stop_at_type<double>>, meta_ret_last_o<exp_list<int>>, meta_ret_decreasible_o<TL>>::type;

int main() {
    using t = cut_at_type<double, exp_list<int, int, int, int, double>>;//t = exp_list<int, int, int, int, double>
    std::cout << typeid(t).name();
}
```