#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);
}

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐