#include <iostream>
#include "common/log.h"
#include <limits>
#include <vector>
#include <span>
#include <array>
#include <type_traits>
using namespace AdsonLib;
//type traits可以在编译期判断一个类型T 是否为数值类型,是否是函数对象,是否是类,是否有构建函数,是不是指针,能否拷贝构造等
//变量模板
template<char c>
constexpr bool is_num_char_v = (c >= '0' && c <= '9');
//fib 使用变量模板
template<unsigned f> constexpr unsigned fib_num_v = fib_num_v<f-1> + fib_num_v<f-2>;
template<> constexpr unsigned fib_num_v<0> = 0;
template<> constexpr unsigned fib_num_v<1> = 1;
//fib 使用类模板
template<size_t n>
struct Fib {
static constexpr size_t value = Fib<n-1>::value + Fib<n-2>::value;
};
template<>
struct Fib<0> {
static constexpr size_t value = 0;
};
template<>
struct Fib<1> {
static constexpr size_t value = 1;
};
template<size_t n>
struct Fib2 {
enum{ value = Fib<n-1>::value + Fib<n-2>::value };
};
template<>
struct Fib2<0> {
enum { value = 0 };
};
template<>
struct Fib2<1> {
enum { value = 1 };
};
constexpr size_t FibFunc(size_t n) {
if(n <= 0) return 0;
if(n <= 2) return 1;
return FibFunc(n-1) + FibFunc(n-2);
}
template<typename, typename ...>
void ShowTypeName() {
LOG(INFO) << __PRETTY_FUNCTION__;
}
void SpanFunc(const std::span<int> &arr) {
LOG(INFO) << "size: " << arr.size();
for(auto && a : arr) {
LOG(INFO) << a;
}
}
int main(int argc, char *argv[]) {
//约定俗成用::value取值
static_assert(std::is_integral<int>::value);
static_assert(!std::is_integral<float>::value);
static_assert(std::is_floating_point<double>::value);
static_assert(!std::is_same<int, double>::value);
static_assert(std::is_class<struct Foo>::value);
static_assert(std::is_pointer<int*>::value);
//type trait
LOG(INFO) << "int max: " << std::numeric_limits<int>::max();
//变量模板
//template<typename T> constexpr bool is_pointer_v = is_pointer<T>::value; 常用的在标准库里这么定义了
static_assert(std::is_pointer_v<int*>);
static_assert(is_num_char_v<'4'>);
static_assert(!is_num_char_v<'x'>);
//0 1 1 2 3 5 8 13 21 34
LOG(INFO) << "fib num 20: " << fib_num_v<20> << " vs " << Fib<20>::value << " vs " << Fib2<20>::value << " vs " << FibFunc(20);
//type trait之类型转换 添加cv限定,添加指针限定
static_assert(std::is_same_v<std::remove_const_t<const int>, int>);
static_assert(std::is_same_v<std::add_const<const int>::type, const int>);
static_assert(std::is_same_v<std::add_pointer_t<const int>, const int *>);
static_assert(std::is_same_v<std::remove_pointer_t<int *>, int>);
ShowTypeName<std::remove_volatile_t<int * volatile>>();
static_assert(std::is_same_v<std::add_volatile_t<int *>, int * volatile>);
static_assert(std::is_same_v<std::remove_volatile_t<int * volatile>, int *>);
//type trait decay 把变量传给函数参数时
ShowTypeName<std::decay_t<int [5][5]>>();
static_assert(std::is_same_v<std::decay_t<int [5][5]>, int (*)[5]>);
static_assert(std::is_same_v<std::decay_t<int &>, int>);
static_assert(std::is_same_v<std::decay_t<const int &>, int>);
int a1[]{1,2,3};
std::vector<int> a2{1,2,3};
std::array a3{1, 2, 3};
SpanFunc(a1);
SpanFunc(a2);
SpanFunc(a3);
//类型和值绑定:编译时
using Two = std::integral_constant<int,2>;
using Four = std::integral_constant<int, 4>;
static_assert(Two::value * Two::value == Four::value);
static_assert(std::bool_constant<true>::value);
static_assert(!std::bool_constant<false>::value);
static_assert(std::true_type::value);
static_assert(!std::false_type::value);
}
C++20 type trait与变量模板 编译期求斐波那契数列
于 2022-12-09 19:00:27 首次发布