现代c++笔记(3)

2021-06-20  本文已影响0人  Teech
template <typename T>
using Vec = std::vector<T, MyAlloc<T>>
Vec<int> coll;
//define也无法达到相同的效果
//typedef 不能接受参数
//不能对偏特化或者全特化起作用

//打算实现这样
//想萃取test_move(vector<MyString>())中的MyString
typdef typename iterator_traits<typename Container::iterator>::value_type ValType;
//template<typename T, template<typename U> class Container> //写法1  
template<typename T, template<class> class Container>       //写法2
class XCls {
private:
    Container<T> c;
public:
    // ...
};
//第一种用法
//typedef void (*fun)();    //传统写法
using func = void(*)(); //新标准写法
void example(){}
fun f = example;
//第二种用法
template<typename T>
struct MyContiner
{
    using mytype = T;//typedef T mytype 
};
//第三种用法 alias tmplelate
template<typename charT>
using myString = std::basic_string<charT, std::char_traits<charT>>;
myString<char> str;
//传统写法typedef不能用于模版
typedef std::basic_string<char, std::char_traits<char>> myString2;
myString2 str2;
//导入命名空间
using namespace std;
using std::cout;
//在class种使用using
protected:
    using _Basic::_M_alloc;
//type-alias 以及alias template(c++ 11以后)
//异常如果一直没处理,会一直往调用链往上传递,如果都没处理,最终程序会执行std::abort() 终止程序
//定义一个函数 保证不抛出异常
void foo() noexcept;//void foo() noexcept(true);
//定义一个函数不抛出异常,条件是x.swap(y)不抛出异常
void swap(Type& x,Type& y) noexcept(noexcept(x.swap(y))
{
  x.swap(y);
}
//你需要通知c++(特别是vector),你的移动构造以及赋值构造不会抛出异常也就是noexcept,Then,move构造函数才会被调用当vector扩容时,如果没有申明noecept,那么std::vector不能使用它
//https://stackoverflow.com/questions/8001823/how-to-enforce-move-semantics-when-a-vector-grows                                    
class MyString {
private:
    char* _data;
    size_t len;
public:
    //move constructor
    MyString(MyString&&str) noexcept
        :_data(str._data),len(str.len){
    }
    MyString& operator=(MyString&& str) noexcept
    {
        _data = str._data;
        len = str.len;
        str._data = nullptr;
        return *this;
    }
};

//std::vector<MyString>不停push_back当发生扩容的时候,到底使用拷贝构造函数还是移动构造函数看MyString种移动构造函数到底有没有申明noexcept 
//正常情况下,移动构造以及移动赋值都要申明成noexcept,这样不论使用的容器时申明都会比较安心  
class base {
    virtual void fun(float a){}
};
class derived :base {
    //这么写会导致新的函数申明
    //virtual void fun(int a) {}
    //override帮助编译器,如果函数原型不一致会导致编译出错
    virtual void fun(int a) override {}
};
//修饰class表示不能被继承,我是最后一个
class base1 final {
};
class derived :base1 {}
};
//修饰虚函数表示不能被override 否则编译出错
class base2 {
    virtual void fun() final {} 
};
class devived :base2
{
    virtual void fun() {}
};
std::map<int, float> coll;
decltype(coll)::value_type elem;//11之前只能std::map<int, float>::value_type elem
//1.申明返回类型,c++11之前
//打算这么写 但是编译不过 x + y在之前出现
template<typename T1,typename T2>
decltype(x + y) add(T1 x,T2 y);
//所以这么写
//很像lambda
template<typename T1,typename T2>
auto add(T1 x,T2 y) ->decltype(x + y);//auto + -> 指明返回类型
//2.metaprograming 模板
template <typename T>
void test(T obj){
  typedef typename decltype(obj)::iterator iType;
  //typedef typename T::iterator iType;
}
//3.获取lambda的类型
auto cmp = [](const P& p1,const P& p2){
  return p1.lastname() < p2.lastname();
}
std::set<P,decltype(cmp)> col(cmp);
lambda是个inline 函数或者可以理解临时对象
  auto l = [] {
  std::cout << 11;
    };
    l(); 
//完整形式
[...](...) mutable(opt) throwSpec(opt) -> retType(opt){...}
[...]:导入器
(...):参数
retType:返回类型
{...}:函数本体
//例子:
int x = 0;
int y = 1;
auto q = [x,&y]{...};//&修饰为传递引用的方式 x为传值的方式
auto q = [=,&y]{...};//=号表示其他外部区域以传值的方式传递

//例子:
    int id = 0;
    //如果不加mutable ++id不能编译通过 如果传递引用的方式过来就可以
    auto f = [id]()mutable {
        std::cout << id << std::endl;
        ++id;
    };
    id = 42;
    f();
    f();
    std::cout << id << std::endl;
//主要id是传值的方式传递过去的
>out: 0 1 42
lambda相当于匿名的函数对象
class Functor {
private:
    int id;
public:
    void operator()() {
        std::cout << id << std::endl;
    }
};
上一篇下一篇

猜你喜欢

热点阅读