一、各个模块
1、将数组转换为指针
// decay_array to pointer
template
auto decay_array(T(&array)[N])
{
return array;
}
2、定义初始模板类型
1)元素类型为T
2)容器类型为T
3)是否为字符数组类型:否
4)数组大小:0
// primary class template
template
struct container_element_st
{
using type = T;
using element_type = T;
static constexpr bool is_character_array = false;
static constexpr size_t array_count = 0;
};
3、定义字符数组类型
1)元素类型为char
2)容器类型为std::string
3)是否为字符数组类型:是
4)数组大小:N
template
struct container_element_st // non reference
{
using type = char;
using element_type = std::string;
static constexpr bool is_character_array = true;
static constexpr size_t array_count = N;
};
4、定义字符指针类型
1)元素类型为char
2)容器类型为std::string
3)是否为字符数组类型:是
4)数组大小:0
template<>
struct container_element_st // non reference
{
using type = char;
using element_type = std::string;
static constexpr bool is_character_array = true;
static constexpr size_t array_count = 0;
};
5、定义非字符类型数组
1)元素类型为T
2)容器类型为std::vector
3)是否为字符数组类型:否
// array but not character array
template
struct container_element_st
{
using type = T;
using element_type = std::vector;
static constexpr bool is_character_array = false;
};
6、定义初始化列表类型
1)元素类型为T
2)容器类型为std::vector
3)是否为字符数组类型:否
// from initializer_list to vector conversion
template
struct container_element_st>
{
using type = T;
using element_type = std::vector;
static constexpr bool is_character_array = false;
};
7、定义各种类型
1)是否为字符数组类型
2)获取字符数组的大小
3)获取字符数组的类型,char or wchar_t
4)获取容器类型
// get whethere character array
template
constexpr auto is_character_array_v = container_element_st>::is_character_array;
// get array size
template
constexpr auto array_count_v = container_element_st< tft::remove_const_reference_t>::array_count;
// define element type
template
using element_flat_t = typename container_element_st< tft::remove_const_reference_t>::type;
// define container element type
template
using container_element_t = typename container_element_st< tft::remove_const_reference_t>::element_type;
8、创建自定义元组
创建元组的时候,元组的元素可以是元组,可以使vector,也可以是各种基础类型元素。
template
auto make_tuple(Type&& first, Types&&... args)
{
using container_t = std::tuple, container_element_t...>;
return container_t{ element_to_container(std::forward(first)),
element_to_container(std::forward(args))... };
}
9、获取自定义元组中的元素
分别可以获取一层元组的元素、两层元组的元素、三层元组的元素。
template
decltype(auto) get(CntrType& cntr)
{
return std::get(cntr);
}
template
decltype(auto) get(CntrType& cntr)
{
if constexpr (sizeof...(Indices) > 0)
return get(get(cntr));
else
return get(cntr);
}
template
decltype(auto) get(CntrType& cntr, IndexType index)
{
if constexpr (sizeof...(Indices) > 0)
return get(get(cntr))[index];
else
return get(cntr)[index];
}
二、整体代码
#include "tft_type_lib.h"
#include "tpf_type_util.h"
auto stream = tpf::stream(); // stream
auto nl = stream.get_console_out(); // new line
// decay_array to pointer
template
auto decay_array(T(&array)[N])
{
return array;
}
// primary class template
template
struct container_element_st
{
using type = T;
using element_type = T;
static constexpr bool is_character_array = false;
static constexpr size_t array_count = 0;
};
template
struct container_element_st // non reference
{
using type = char;
using element_type = std::string;
static constexpr bool is_character_array = true;
static constexpr size_t array_count = N;
};
template<>
struct container_element_st // non reference
{
using type = char;
using element_type = std::string;
static constexpr bool is_character_array = true;
static constexpr size_t array_count = 0;
};
template
struct container_element_st // non reference
{
using type = wchar_t;
using element_type = std::wstring;
static constexpr bool is_character_array = true;
static constexpr size_t array_count = N;
};
template<>
struct container_element_st // non reference
{
using type = wchar_t;
using element_type = std::wstring;
static constexpr bool is_character_array = true;
static constexpr size_t array_count = 0;
};
// array but not character array
template
struct container_element_st
{
using type = T;
using element_type = std::vector;
static constexpr bool is_character_array = false;
};
template
struct container_element_st
{
using type = T;
using element_type = std::vector;
static constexpr bool is_character_array = false;
};
// from initializer_list to vector conversion
template
struct container_element_st>
{
using type = T;
using element_type = std::vector;
static constexpr bool is_character_array = false;
};
// get whethere character array
template
constexpr auto is_character_array_v = container_element_st>::is_character_array;
// get array size
template
constexpr auto array_count_v = container_element_st< tft::remove_const_reference_t>::array_count;
// define element type
template
using element_flat_t = typename container_element_st< tft::remove_const_reference_t>::type;
// define container element type
template
using container_element_t = typename container_element_st< tft::remove_const_reference_t>::element_type;
// create a vector
template
auto make_vector(Type&& first, Types&&... args)
{
// determine whether type argument is an array
if constexpr (std::is_array_v>)
{
// this is to allow only character array
static_assert(is_character_array_v, "should be character array");
using element_t = container_element_t;
using container_t = std::vector;
size_t size = array_count_v;
const auto& last_character = first[size - 1];
// last character is NULL character
if (element_flat_t{} == last_character)
return container_t{ decay_array(first),decay_array(args)... };
else
{
return container_t{ element_t{std::cbegin(first),std::cend(first)},
element_t{std::cbegin(args),std::cend(args)}... };
}
}
else
{
using element_t = tft::remove_const_reference_t;
return std::vector{ std::forward(first), std::forward(args)... };
}
}
// 创建一个容器
template< template class CntrType, typename Type, typename... Types>
auto make_container(Type&& first, Types&&... args)
{
if constexpr (std::is_array_v>)
{
// this is to allow only character only
static_assert(is_character_array_v, "should be character array");
using element_t = container_element_t;
using container_t = CntrType;
size_t size = array_count_v;
const auto& last_character = first[size - 1];
// last character is NULL character
if (element_flat_t{} == last_character)
return container_t{ decay_array(first),decay_array(args)... };
else
{
return container_t{ element_t{std::cbegin(first),std::cend(first)},
element_t{std::cbegin(args),std::cend(args)}... };
}
}
else
{
using element_t = tft::remove_const_reference_t;
return CntrType{ std::forward(first), std::forward(args)... };
}
}
template
void print_type(T&& arg)
{
stream << "Type of T:" << Tpf_GetTypeName(T)
<< ", Type of arg: " << Tpf_GetTypeCategory(decay_array(arg)) << nl;
}
void simple_tip()
{
int a = 1;
std::vector v1{ 1,2,3,4,5 };
auto v2 = make_vector(a, 2, 3, 4, 5, 6, 7, 8, 9, 10);
stream << "v1 = " << v1 << nl;
stream << "v2 = " << v2 << nl;
auto v3 = make_vector("123", "tomas kim", "han", "saimei", "shuang");
stream << "v3 = " << v3 << nl;
}
void simple_tip_advance()
{
int a = 1;
std::vector v1{ 1,2,3,4,5 };
auto v2 = make_container(a, 2, 3, 4, 5, 6, 7, 8, 9, 10);
stream << "v1 = " << v1 << nl;
stream << "v2 = " << v2 << nl;
auto v3 = make_container("123", "tomas kim", "han", "saimei", "shuang");
stream << "v3 = " << v3 << nl;
}
/*
we have to convert const char* to std::string
const wchar_t* to std::wstring
convert array,int[] to std::vector
std::initializer_list<> to std::vector<>
*/
template
auto element_to_container(Type&& arg)
{
// array such as char[N],int[N] ect.
if constexpr (std::is_array_v>)
{
if constexpr (is_character_array_v)
{
// character array ,we convert
// const char* to std::string
// const wchar_t* to std::wstring
// char[N] to std::string
// wchar_t[N] to std::wstring
using element_t = container_element_t;
size_t size = array_count_v;
const auto& last_character = arg[size - 1];
// element_flat_t returns either char or wchar_t
// testing if zero terminated character
if (element_flat_t{} == last_character)
return element_t{ decay_array(arg) };// decay_array() convert char[] to char*
else // not zero terminating character array
return element_t{ std::cbegin(arg),std::cend(arg) };
}
else
{
// non character array
using element_t = container_element_t;
return element_t{ std::cbegin(arg),std::cend(arg) };
}
}
else
{
// non array case
using element_t = container_element_t;
return element_t{ std::forward(arg) };
}
}
// this belongs to non-deduced context
template
auto element_to_container(std::initializer_list& lst)
{
// decltype(lst),decltype(),get variable type
// using element_t = container_element_t>;
using element_t = container_element_t;
// conversion from std::initializer_list to std::vector
return element_t{ lst };
}
// this belongs to non-deduced context
template
auto element_to_container(std::initializer_list&& lst)
{
// decltype(lst),decltype(),get variable type
// using element_t = container_element_t>;
using element_t = container_element_t;
// conversion from std::initializer_list to std::vector
return element_t{ std::forward>(lst) };
}
template
auto make_tuple(Type&& first, Types&&... args)
{
using container_t = std::tuple, container_element_t...>;
return container_t{ element_to_container(std::forward(first)),
element_to_container(std::forward(args))... };
}
template
decltype(auto) get(CntrType& cntr)
{
return std::get(cntr);
}
template
decltype(auto) get(CntrType& cntr)
{
if constexpr (sizeof...(Indices) > 0)
return get(get(cntr));
else
return get(cntr);
}
template
decltype(auto) get(CntrType& cntr, IndexType index)
{
if constexpr (sizeof...(Indices) > 0)
return get(get(cntr))[index];
else
return get(cntr)[index];
}
void test_element_to_container()
{
using literal_string_t = const char*;
auto str1 = element_to_container("This is literal string");
stream << "str1 = " << str1 << "\nType: "
<< Tpf_GetTypeCategory(str1) << nl;
int array[]{ 1,2,3,4,5 };
auto vtr1 = element_to_container(array);
stream << "vtr1 = " << vtr1 << "\nType: "
<< Tpf_GetTypeCategory(vtr1) << nl;
auto lst = element_to_container({ 3.1,5.0,6.0 });
stream << "lst = " << lst << "\nType: "
<< Tpf_GetTypeCategory(lst) << nl;
}
void test_make_tuple()
{
const char* msg1 = "Literal string";
const wchar_t* msg2 = L"wide character string";
auto t1 = make_tuple(msg1,"han", "shuang", "shuang han", 20, "sia mie",msg2);
stream << "t1 = " << t1 << /*"\nType: "
<< Tpf_GetTypeCategory(t1) <<*/ nl;
using t1_0_th_t = std::tuple_element_t<0, decltype(t1)>;
stream << "t1-0-th element: " << std::get<0>(t1) << "\n Type: "
<< Tpf_GetTypeName(t1_0_th_t) << nl;
using t1_4_th_t = std::tuple_element_t<4, decltype(t1)>;
stream << "t1-4-th element: " << std::get<4>(t1) << "\n Type: "
<< Tpf_GetTypeName(t1_4_th_t) << nl;
using t1_6_th_t = std::tuple_element_t<6, decltype(t1)>;
stream << "t1-6-th element: " << std::get<6>(t1) << "\n Type: "
<< Tpf_GetTypeName(t1_6_th_t) << nl;
}
void test_advanced_make_tuple()
{
auto t1 = make_tuple(
make_tuple(1, 3.14, "han"),
make_tuple(make_vector(1, 2, 3, 4, 5), make_vector(3.0, 5.0, 6.1),
make_tuple("han", "s shuang", 40.2f)),
make_vector("james", "seveten"));
stream << t1 << nl;
stream << get<0>(t1) << nl;
stream << get<1>(t1) << nl;
stream << get<1, 0>(t1) << nl;
stream << get<1, 1>(t1) << nl;
stream << get<1, 2>(t1) << nl;
stream << nl;
//get<1, 0>(t1) is a vector
for (const auto& e : get<1, 0>(t1))
stream << e << " ";
stream << nl;
}
int main()
{
//test_element_to_container();
//test_make_tuple();
test_advanced_make_tuple();
return 0;
}