前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++模版笔记(1)

C++模版笔记(1)

作者头像
一只小虾米
发布2022-10-25 16:52:00
2250
发布2022-10-25 16:52:00
举报
文章被收录于专栏:Android点滴分享

本篇介绍

本篇摘录自<<C++ templates>>,记录其中部分内容。

Variadic Templates

操作可变参数

代码语言:javascript
复制
template <typename T>
void func(T arg) {
    std::cout<< arg << std::endl;
}

template <typename T, typename ... Types>
void func(T firstArg, Types... args) {
    func(firstArg);
    func(args...);
}

使用sizeof...(args)即可获取到变量个数。

在c++ 17上可以按照如下方式操作可变入参:

代码语言:javascript
复制
template <typename... T>
auto sum(T... s) {
    return (... + s);  // ((s1 +s2) + s3)
}

具体格式如下:

image.png

std::enable_if

利用SFINE性质,也就是只要可以匹配成功,即使某些场景匹配失败也不是错误。

代码语言:javascript
复制
template<bool B, class T = void>
struct enable_if {};
 
template<class T>
struct enable_if<true, T> { typedef T type; };

using 在模版中的使用

using 有给类型重命名的作用,也有继承父类所有构造函数的作用,比如:

代码语言:javascript
复制
struct Base {
    int val;
    Base() { val = 0;}
    Base(int m):val(m) {
    }
};

struct Derived : public Base {
    using Base::Base;
};

通过using 就可以一下子使用到父类的所有构造函数。

也可以通过模版支持获取所有类的操作符重载方法:

代码语言:javascript
复制
class Customer
{
  private:
    std::string name;
  public:
    Customer(std::string const& n) : name(n) { }
    std::string getName() const { return name; }
};

struct CustomerEq {
      bool operator() (Customer const& c1, Customer const& c2) const {
        return c1.getName() == c2.getName();
      }
};
  struct CustomerHash {
      std::size_t operator() (Customer const& c) const {
        return std::hash<std::string>()(c.getName());
      }
};

template<typename... Bases>
struct Overloader : Bases...
{
    using Bases::operator()...;
};

using CustomerOP = Overloader<CustomerHash,CustomerEq>;

std::unordered_set<Customer,CustomerOP,CustomerOP> col;

typename

在模版使用过程中,typename 和class 是等同的,不过typename还有一层含义,就是修饰的参数一定是类型。

代码语言:javascript
复制
 template<typename T>
   class MyClass {
public: ...
       void foo() {
         typename T::SubType* ptr;  
} };

这儿的 T::SubType 是类型。

模版友元

如果希望支持模版不同特化之间可以访问私有数据,那么就可以设置模版特化是友元的。

代码语言:javascript
复制
template <typename T> 
class Stack {
template <typename> friend class Stack;
};

变量模版

可以用变量来表示类模版的成员值:

代码语言:javascript
复制
 namespace std {
     template<typename T> constexpr bool is_const_v = is_const<T>::value;
}

这样通过is_const_v<T> 就可以表示 is_const<T>::value

模版模版参数

如果模版参数中的类型本身也是一个模版,比如还是Stack, Stack<int, std::vector<int>> 可以看到第一个模版参数是int,第二个模版参数还是一个int,这时候就是模版的模版参数了,要声明这种场景,方法如下:

代码语言:javascript
复制
template<typename T,
          template<typename Elem> class Cont = std::deque>

在模版里再写一下 template<typename Elem>,就表明第二个参数也是模版。 这时候完整的Stack 如下:

代码语言:javascript
复制
#include <deque>
#include <cassert>
#include <memory>
template<typename T,
           template<typename Elem,
                    typename = std::allocator<Elem>>
            class Cont = std::deque>
 class Stack {
  private:
    Cont<T> elems;
  public:
    void push(T const&);
    void pop();
    T const& top() const;
    bool empty() const {
    return elems.empty();
}
// assign stack of elements of type T2 template<typename T2,
 template<typename Elem2,
                      typename = std::allocator<Elem2>
                     >class Cont2>
    Stack<T,Cont>& operator= (Stack<T2,Cont2> const&);
// to get access to private members of any Stack with elements of type T2: template<typename, template<typename, typename>class> friend class Stack;
};

template<typename T, template<typename,typename> class Cont>
void Stack<T,Cont>::push (T const& elem)
{
elems.push_back(elem); // append copy of passed elem 
}

template<typename T, template<typename,typename> class Cont>
void Stack<T,Cont>::pop ()
{
    assert(!elems.empty());
    elems.pop_back();
// remove last element
}
template<typename T, template<typename,typename> class Cont>
T const& Stack<T,Cont>::top () const
{
    assert(!elems.empty());
return elems.back(); // return copy of last element 
}

template<typename T, template<typename,typename> class Cont>
 template<typename T2, template<typename,typename> class Cont2>
Stack<T,Cont>&
Stack<T,Cont>::operator= (Stack<T2,Cont2> const& op2)
{
elems.clear();
elems.insert(elems.begin(),
             op2.elems.begin(),
             op2.elems.end());
return *this;
// remove existing elements // insert at the beginning
// all elements from op2
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-08-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 本篇介绍
  • Variadic Templates
    • 操作可变参数
      • std::enable_if
        • using 在模版中的使用
          • typename
            • 模版友元
              • 变量模版
                • 模版模版参数
                领券
                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档