#include <iostream>
#include <utility>
using namespace std;
namespace tp1
{
template<typename T, typename U = std::void_t<>>
struct HasMemFunc : std::false_type
{
};
template<typename T>
struct HasMemFunc<T, std::void_t<decltype(std::declval<T>().func_())>>:std::true_type
{
};
template <typename ...T>
class Tup1E;
template<typename first, typename ...others>
class Tup1E<first, others...>
{
public:
first _first;
Tup1E<others...> _others;
public:
Tup1E()
{
}
template<typename c_first, typename...c_others,
typename = std::enable_if_t<!HasMemFunc<c_first>::value>
>
Tup1E(c_first&& parf, c_others&&... paro) :
_first(std::forward<c_first>(parf)),
_others(std::forward<c_others>(paro)...)
{
cout << "Tup1E c_first, c_others::"<< endl;
}
Tup1E(const Tup1E<first, others...>& tmptp1) : _first(tmptp1._first), _others(tmptp1._others)
{
cout << "Tup1E(const Tup1E<first, others...)" << endl;
}
//拷贝构造函数与拷贝构造模版是两个东西, 拷贝造函数如果没有匹配且类型不同 的会执行拷贝构造模版
template<typename c_first, typename...c_others>
Tup1E(const Tup1E<c_first, c_others...>& tmptp1) : _first(tmptp1._first), _others(tmptp1._others)
{
}
public:
void func_()
{
}
};
template<>
class Tup1E<>
{
public:
Tup1E()
{
cout << "Tup1E<> Tup1E()" << endl;
}
Tup1E(const Tup1E<>&)
{
cout << "Tup1E<> Tup1E(const Tup1E<>&)" << endl;
}
};
template <int index>
class TPLGetIdx
{
public:
template <typename first, typename ...others>
static auto myget(const Tup1E<first, others...>& tmptpl)
{
return TPLGetIdx<index - 1>::myget(tmptpl._others);
}
};
template<>
class TPLGetIdx<0>
{
public:
template<typename first, typename ...others>
static auto myget(const Tup1E<first, others...>& tmptp1)
{
return tmptp1._first;
}
};
template<int index, typename ... types>
auto TPLGet(const Tup1E<types...>& tmptp1)
{
return TPLGetIdx<index>::myget(tmptp1);
}
template <typename TPLE>
class pop_front_type;
template <typename first, typename ...others>
class pop_front_type<Tup1E<first, others...>>
{
public:
using type = Tup1E<others...>;
};
//template <typename... ElemsTypes, typename NewType>
//auto push_front(const Tup1E<ElemsTypes...>& tmptuple, const NewType& tmpvalue)
//{
// return Tup1E<NewType, ElemsTypes ...>(tmpvalue, tmptuple);
//}
template<typename newType>
auto push_front(const Tup1E<>& tmptuple, const newType& tmpvalue)
{
return Tup1E<newType>(tmpvalue);
}
template<typename firstType, typename ... othersType, typename newType>
auto push_front(const Tup1E<firstType, othersType...>& tmpTuple, const newType& tmpValue)
{
//return Tup1E<newType, firstType, othersType...>
// (tmpValue, push_front(tmpTuple._others, tmpTuple._first));
return Tup1E<newType, firstType, othersType...>
(tmpValue, push_front(tmpTuple._others, tmpTuple._first));
}
template <typename newType>
auto push_back(const Tup1E<>&, const newType& tmpvalue)
{
return Tup1E<newType>(tmpvalue);
}
template<typename firstType, typename ...otherType, typename newType>
auto push_back(const Tup1E<firstType, otherType...>& tmpTuple, const newType& tmpValue)
{
return Tup1E<firstType, otherType..., newType>
(tmpTuple._first, push_back(tmpTuple._others, tmpValue));
}
template <typename ...ElemsTypes>
auto pop_front(const Tup1E<ElemsTypes...>& tmpTuple)
{
return tmpTuple._others;
}
auto reverse(const Tup1E<>&)
{
return Tup1E<>();
}
template<typename firstType, typename... othersType>
auto reverse(const Tup1E<firstType, othersType...>& tmpTuple)
{
return push_back(reverse(tmpTuple._others), tmpTuple._first);
}
}
//函数模板可以通过实参中给进来的元素值推导出元素的类型
template<typename ...Types>
auto Make_tuple(Types&&..._args)
{
return tp1::Tup1E<std::decay_t<Types>...>(std::forward<Types>(_args)...);
}
int main(int arg, char** args)
{
int i = 1000;
tp1::Tup1E<float, int, bool> obj(13.1f, 5, true);
tp1::Tup1E<double, int, bool> obj2(obj);
std::cout << tp1::TPLGet<2>(obj) << std::endl;
auto mytuple = Make_tuple(12.5f, 100, true);
tp1::Tup1E<float, int, std::string> cobj(12.5f, 100, "test");
tp1::pop_front_type<decltype(cobj)>::type cobj2(100, "test");
std::cout << tp1::TPLGet<1>(cobj2) << std::endl;
tp1::Tup1E<> obj3;
auto cobj4 = tp1::push_front(obj3, 14);
auto obj7 = tp1::push_back(cobj4, 15);
auto obj8 = tp1::push_back(obj7, 17);
auto obj9 = tp1::pop_front(obj8);
auto obj10 = tp1::reverse(obj9);
return 0;
}