【 声明:版权所有,转载请标明出处,请勿用于商业用途。 联系信箱:[email protected]】
16.1 定义模板
1.模板定义以关键字template开始,后跟一个模板参数列表,这是一个逗号分隔的一个或多个模板参数的列表,用小于号(<)和大于号(>)包围起来。在模板定义中,模板参数列表不能为空。
2.模板知道实力化时才会生成代码,这一特性影响了我们何时才睡获知模板内代码的编译错误。通常,编译器会在三个阶段报告错误。
第一个阶段是编译模板本身时。在这个阶段,编译器通常不会发现很多错误。编译器可以检查语法错误,例如忘记分号或者变量名拼错等,但也就这么多了。
第二个阶段是编译器遇到模板使用时。在此阶段,编译器仍然没有很多可检查的。对于函数模板调用,编译器通常会检查实参数目是否正确。它还能检查参数类型是否匹配。对于类模板,编译器可以检查用户是否提供了正确数目的模板实参,但也仅限于此了。
第三个阶段是模板实例化时,只有在这个阶段才能发现类型相关的错误。依赖于编译器如何管理实例化,这类错误可能在链接时才报告。
3.一个类(无论是普通类还是类模板)可以包含本身是模板的成员函数。这种成员被称为成员模板。成员模板不能是虚函数。
16.2 模板实参推断
1.从函数实参来确定模板实参的过程被称为模板实参推断。在模板实参推断过程中,编译器使用函数调用中的实参类型来寻找模板实参,用这些模板实参生成的函数版本与给定的函数调用最为匹配。
2.顶层const无论实在形参中还是在实参中,都会被忽略。在其他类型转换中,能在调用中应用于函数模板的包括如下两项。
⑴const转换:可以将一个非const对象的引用(或指针)传递给一个const的引用(或指针)形参。
⑵数组或函数指针转换:如果函数形参不是引用类型,则可以对数组或函数类型的实参应用正常的指针转换。一个数组实参可以转换为一个指向其首元素的指针。类似的,一个函数实参可以转换为一个该函数类型的指针。
3.
如果一个函数参数是一个指向模板类型参数的右值引用(如T&&),则它可以被绑定到一个左值
如果实参是一个左值,则推断出的模板实参类型将是一个左值引用,且函数参数将被实例化为一个左值引用参数(T&)
16.3 重载与模板
1.函数匹配规则会在以下几个方面受到影响:
⑴对于一个调用,其候选函数包括所有模板实参推断成功的函数模板实例
⑵候选的函数模板总是可行的,因为模板实参推断会排除任何不可行的模板
⑶与往常一样,可行函数(模板与非模板)按类型转换来排序。当然,可以用于函数模板调用的类型转换是非常有限的。
⑷与往常一样,如果恰有一个函数提供比任何其他函数都更好的匹配,则选择此函数。但是如果有多个函数提供同样更好的匹配,则:
-如果同样好的函数中只有一个是非模板函数,则选择此函数
-如果同样好的函数中没有非模板函数,而有多个函数模板,且其中一个模板比其他模板更特丽花,则选择此模板
-否则,此调用有歧义
16.4 可变参数模板
1.一个可变参数模板,就是一个接受可变数目参数的模板函数或模板类。可变数目的参数被称为参数包。存在两种参数包:模板参数包,表示零个或多个模板参数;函数参数包,表示零个或多个函数参数。
PS:部分练习答案
练习16.4
#include <iostream> #include <vector> #include <list> #include <string> template<typename iteratorT, typename valueT> iteratorT find(const iteratorT& first, const iteratorT& last,const valueT& value ) { auto iter = first; while(iter != last && *iter != value) ++iter; return iter; } int main() { std::vector<int> vi = {1,2,3,4,5,6,7,8,9}; auto it = find(vi.cbegin(), vi.cend(), 5); std::cout << *it << std::endl; std::list<std::string> l = {"aa","bb","cc","dd","ee","ff","gg"}; std::list<std::string>::const_iterator itL = find(l.cbegin(), l.cend(), "ee"); std::cout << *itL << std::endl; return 0; }
#include <iostream> #include <string> template<typename Arr> void print(const Arr& a) { for(const auto& elem : a) std::cout << elem << std::endl; } int main() { std::string p[] = {"ssss","aaa","ssssss"}; char c[] = {'a','b','c','d'}; int i[] = {1}; print(i); print(c); print(p); std::cout << "\nexit normally\n"; return 0; }
#include <iostream> #include <vector> #include <list> #include <string> template<typename T, unsigned size> T* begin(const T(&arr)[size]) { return arr; } template<typename T, unsigned size> T* end(const T (&arr)[size]) { return arr + size; } int main() { std::string s[] = {"sssss","ss","ss","ssssszzzz"}; std::cout << *(begin(s)+1) << std::endl; std::cout << *(end(s) - 1) << std::endl; return 0; }
#include <iostream> #include <vector> #include <list> #include <string> template<typename T, unsigned size> constexpr unsigned getSize(const T(&)[size]) { return size; } int main() { std::string s[] = {"sss"}; std::cout << getSize(s) << std::endl; char c[] = "s"; std::cout << getSize(c) << std::endl; return 0; }
vec.h
#ifndef VEC_H #define VEC_H #include <memory> template<typename T> class Vec { public: Vec():element(nullptr), first_free(nullptr), cap(nullptr) { } Vec(std::initializer_list<T> l); Vec(const Vec& v); Vec& operator =(const Vec& rhs); ~Vec(); //! memmbers void push_back(const T& t); std::size_t size() const { return first_free - element; } std::size_t capacity()const { return cap - element; } T* begin() const { return element; } T* end() const { return first_free; } void reserve(std::size_t n); void resize(std::size_t n); void resize(std::size_t n, const T& t); private: //! data members T* element; T* first_free; T* cap; std::allocator<T> alloc; //! utillities void reallocate(); void chk_n_alloc() { if(size()==capacity()) reallocate(); } void free(); void wy_alloc_n_move(std::size_t n); std::pair<T*, T*> alloc_n_copy(T* b, T* e); }; //! copy constructor template<typename T> Vec<T>::Vec(const Vec &v) { std::pair<T*,T*> newData = alloc_n_copy(v.begin(), v.end()); element = newData.first; first_free = cap = newData.second; } //! constructor that takes initializer_list<T> template<typename T> Vec<T>::Vec(std::initializer_list<T> l) { //! allocate memory as large as l.size() T* const newData = alloc.allocate(l.size()); //! copy elements from l to the address allocated T* p = newData; for(const auto &t : l) alloc.construct(p++, t); //! build data structure element = newData; first_free = cap = element + l.size(); } //! operator = template<typename T> Vec<T>& Vec<T>::operator =(const Vec& rhs) { //! allocate and copy first to protect against self_assignment std::pair<T*,T*> newData = alloc_n_copy(rhs.begin(), rhs.end()); //! destroy and deallocate free(); //! update data structure element = newData.first; first_free = cap = newData.second; return *this; } //! destructor template<typename T> Vec<T>::~Vec() { free(); } template<typename T> void Vec<T>::push_back(const T &t) { chk_n_alloc(); alloc.construct(first_free++, t); } template<typename T> void Vec<T>::reserve(std::size_t n) { //! if n too small, just return without doing anything if(n <= capacity()) return; //! allocate new memory and move data from old address to the new one wy_alloc_n_move(n); } template<typename T> void Vec<T>::resize(std::size_t n) { resize(n, T()); } template<typename T> void Vec<T>::resize(std::size_t n, const T &t) { if(n < size()) { //! destroy the range [element+n, first_free) using destructor for(auto p = element + n; p != first_free; ) alloc.destroy(p++); //! update first_free to point to the new address first_free = element + n; } else if(n > size()) { for (auto i = size(); i != n; ++i) push_back(t); } } template<typename T> std::pair<T*,T*> Vec<T>::alloc_n_copy(T *b, T *e) { //! calculate the size needed and allocate space accordingly T* data = alloc.allocate(e-b); return { data, std::uninitialized_copy(b, e, data)}; } template<typename T> void Vec<T>::free() { //! if not nullptr if(element) { //! destroy it in reverse order. for(auto p = first_free; p != element; ) alloc.destroy(--p); alloc.deallocate(element,capacity()); } } template<typename T> void Vec<T>::wy_alloc_n_move(std::size_t n) { //! allocate as required. std::size_t newCapacity = n; T* newData = alloc.allocate(newCapacity); //! move the data from old place to the new one T* dest = newData; T* old = element; for(std::size_t i = 0; i != size(); ++i) alloc.construct(dest++, std::move(*old++)); free(); //! update data structure element = newData; first_free = dest; cap = element + newCapacity; } template<typename T> void Vec<T>::reallocate() { //! calculate the new capacity required std::size_t newCapacity = size() ? 2 * size() : 1; //! allocate and move old data to the new space wy_alloc_n_move(newCapacity); } #endif
#include "vec.h" #include <vector> #include <iostream> int main() { Vec<int> v = {1,2,3,4,5}; Vec<int> v2; v2 = v; std::cout << v2.capacity() << "\n"; v2.push_back(99); v2.resize(2,2); for (auto t : v2) std::cout << t << " "; std::cout << v2.capacity() << "\n"; return 0; }
#include <iostream> #include <vector> #include <list> //! ex16.19 using size() to control the loop template<typename Container> std::ostream & print(Container &c, std::ostream &os) { typedef typename Container::size_type size_type; auto it = c.begin(); for(size_type i = 0; i!= c.size(); ++i) os << *it++ << "\n"; return os; } //! ex16.20 using iterator to control the loop template<typename Container> std::ostream& print2(Container& c, std::ostream &os) { for (auto it = c.begin(); it != c.end(); ++it) os << *it << "\n"; return os; } int main() { std::vector<int> v = {1,23,6,4,5,7,4}; std::list<std::string> l = {"ss","sszz","saaas","s333s","ss2","sss"}; print2(v, std::cout); print2(l, std::cout); return 0; }
DebugDelete.h
#ifndef DEBUGDELETE_H #define DEBUGDELETE_H #include <iostream> class DebugDelete { public: DebugDelete(std::ostream& s = std::cerr) : os(s) { } template<typename T> void operator() (T* p) const { os << "deleting unique_ptr" << std::endl; delete p; } private: std::ostream& os; }; #endif
#ifndef STRBLOB_H #define STRBLOB_H #include <vector> #include <string> #include <initializer_list> #include <memory> #include <stdexcept> class StrBlobPtr; class StrBlob { friend class StrBlobPtr; public: typedef std::vector<std::string>::size_type size_type; StrBlob() : data(std::make_shared<std::vector<std::string>>()) { } StrBlob(std::initializer_list<std::string> il); size_type size() const { return data->size(); } bool empty() const { return data->empty(); } void push_back(const std::string &t) { data->push_back(t); } void pop_back(); std::string& front(); std::string& back(); StrBlobPtr begin(); StrBlobPtr end(); private: std::shared_ptr<std::vector<std::string>> data; void check(size_type i, const std::string &msg) const; }; inline StrBlob::StrBlob(std::initializer_list<std::string> il): data(std::make_shared<std::vector<std::string>>(il)) { } class StrBlobPtr { friend bool eq(const StrBlobPtr&, const StrBlobPtr&); public: StrBlobPtr(): curr(0) { } StrBlobPtr(StrBlob &a, size_t sz = 0) : wptr(a.data), curr(sz) { } StrBlobPtr(const StrBlob &a, const size_t sz = 0) : wptr(a.data), curr(sz) { } std::string& deref() const; StrBlobPtr& incr(); StrBlobPtr& decr(); private: std::shared_ptr<std::vector<std::string>> check(std::size_t, const std::string&) const; std::weak_ptr<std::vector<std::string>> wptr; std::size_t curr; }; inline std::string& StrBlobPtr::deref() const { auto p = check(curr, "dereference past end"); return (*p)[curr]; } inline std::shared_ptr<std::vector<std::string>> StrBlobPtr::check(std::size_t i, const std::string &msg) const { auto ret = wptr.lock(); if (!ret) throw std::runtime_error("unbound StrBlobPtr"); if (i >= ret->size()) throw std::out_of_range(msg); return ret; } inline StrBlobPtr& StrBlobPtr::incr() { check(curr, "increment past end of StrBlobPtr"); ++curr; return *this; } inline StrBlobPtr& StrBlobPtr::decr() { --curr; check(-1, "decrement past begin of StrBlobPtr"); return *this; } inline StrBlobPtr StrBlob::begin() { return StrBlobPtr(*this); } inline StrBlobPtr StrBlob::end() { auto ret = StrBlobPtr(*this, data->size()); return ret; } // named equality operators for StrBlobPtr inline bool eq(const StrBlobPtr &lhs, const StrBlobPtr &rhs) { auto l = lhs.wptr.lock(), r = rhs.wptr.lock(); if (l == r) return (!r || lhs.curr == rhs.curr); else return false; } inline bool neq(const StrBlobPtr &lhs, const StrBlobPtr &rhs) { return !eq(lhs, rhs); } #endif
#ifndef WY_TEXTQUERY_H #define WY_TEXTQUERY_H #include <iostream> #include <fstream> #include <vector> #include <string> #include <map> #include <set> #include <memory> class wy_queryResult; class wy_textQuery { public: typedef std::shared_ptr<std::vector<std::string>> sp_file_Tp; typedef std::shared_ptr<std::map<std::string,std::set<int>>> sp_Qmap_Tp; wy_textQuery() = default; wy_textQuery(std::ifstream &fin); wy_queryResult query(const std::string &qWord) const; private: sp_file_Tp sp_fileData = nullptr; sp_Qmap_Tp sp_queryMap = nullptr; }; #endif
#include "wy_textquery.h" #include "wy_queryresult.h" #include "DebugDelete.h" #include <sstream> #include <algorithm> wy_textQuery::wy_textQuery(std::ifstream &fin) : sp_fileData(new std::vector<std::string>(), DebugDelete() ), sp_queryMap(new std::map<std::string, std::set<int>>(), DebugDelete()) { std::string line; while(std::getline(fin, line)) sp_fileData->push_back(line); } wy_queryResult wy_textQuery::query(const std::string &qWord) const { std::size_t counter = 0; for(std::size_t i=0; i != sp_fileData->size(); ++i) { std::stringstream lineStream((*sp_fileData)[i]); std::string word; while(lineStream >> word) { if(!word.compare(qWord)) { ++counter; (*sp_queryMap)[qWord].insert(i); } } } wy_queryResult qResult(counter, qWord, sp_fileData, sp_queryMap); return qResult; }
#ifndef WY_QUERYRESULT_H #define WY_QUERYRESULT_H #include "wy_textquery.h" class wy_queryResult { public: wy_queryResult() = default; wy_queryResult(const wy_queryResult &qr); wy_queryResult(std::size_t c, const std::string &str, const wy_textQuery::sp_file_Tp &sp_f, const wy_textQuery::sp_Qmap_Tp &sp_m); std::size_t getCounter() const { return counter; } std::string getQueryWord() const { return queryWord; } wy_textQuery::sp_file_Tp getSp_file() const { return sp_file; } wy_textQuery::sp_Qmap_Tp getSp_Qmap() const { return sp_Qmap; } private: std::size_t counter = 0; std::string queryWord = ""; wy_textQuery::sp_file_Tp sp_file = nullptr; wy_textQuery::sp_Qmap_Tp sp_Qmap = nullptr; }; void print(std::ostream &os, const wy_queryResult &qr); #endif
#include "wy_queryresult.h" inline wy_queryResult::wy_queryResult(const wy_queryResult &qr): counter(qr.getCounter()), queryWord(qr.getQueryWord()), sp_file(qr.getSp_file()), sp_Qmap(qr.getSp_Qmap()) { } wy_queryResult::wy_queryResult(std::size_t c, const std::string &str, const wy_textQuery::sp_file_Tp &sp_f, const wy_textQuery::sp_Qmap_Tp &sp_m) : counter(c), queryWord(str), sp_file(sp_f), sp_Qmap(sp_m) { } void print(std::ostream &os, const wy_queryResult &qr) { const std::string queryWord = qr.getQueryWord(); os << "The word [" <<queryWord <<"] occurs " <<qr.getCounter() <<" times :\n"; auto sp_m = qr.getSp_Qmap(); auto sp_f = qr.getSp_file(); for(const auto &index : (*sp_m)[queryWord]) std::cout << "\n(Line " <<index <<") " << (*sp_f)[index] << "\n\n"; }
#include <iostream> #include <vector> #include <list> #include "DebugDelete.h" #include <memory> #include "wy_queryresult.h" #include "wy_textquery.h" int main() { return 0; }
#ifndef BLOB_H #define BLOB_H #include <memory> #include <vector> template<typename T> class Blob { public: typedef T value_type; typedef typename std::vector<T>::size_type size_type; Blob(); Blob(std::initializer_list<T> il); template<typename It> Blob(It b, It e); size_type size() const { return data->size(); } bool empty() const { return data->empty(); } void push_back(const T& t) { data->push_back(t); } void push_back(T&& t) { data->push_back(std::move(t)); } void pop_back(); T& back(); T& operator[](size_type i); const T& back() const; const T& operator [](size_type i) const; private: std::shared_ptr<std::vector<T>> data; void check(size_type i, const std::string &msg) const; }; template<typename T> Blob<T>::Blob() : data(std::make_shared<std::vector<T>>()) {} template<typename T> Blob<T>::Blob(std::initializer_list<T> il): data(std::make_shared<std::vector<T>>(il)) { } template<typename T> template<typename It> Blob<T>::Blob(It b, It e) : data(std::make_shared<std::vector<T>>(b,e)) {} template<typename T> void Blob<T>::check(size_type i, const std::string &msg) const { if(i >= data->size()) throw std::out_of_range(msg); } template<typename T> T& Blob<T>::back() { check(0,"back on empty Blob"); return data->back(); } template<typename T> const T& Blob<T>::back() const { check(0,"back on empty Blob"); return data->back(); } template<typename T> T& Blob<T>::operator [](size_type i) { check(i,"subscript out of range"); return (*data)[i]; } template<typename T> const T& Blob<T>::operator [](size_type i) const { check(i,"subscript out of range"); return (*data)[i]; } template<typename T> void Blob<T>::pop_back() { check(0,"pop_back on empty Blob"); data->pop_back(); } #endif
shared_pointer.h
#ifndef SHARED_POINTER_H #define SHARED_POINTER_H #include "DebugDelete.h" #include <functional> template<typename> class shared_pointer; template<typename T> void swap(shared_pointer<T>& lhs, shared_pointer<T>& rhs); template <typename T> class shared_pointer { friend void swap<T>(shared_pointer<T>& lhs, shared_pointer<T>& rhs); public: shared_pointer() = default; explicit shared_pointer(T* up, std::function<void(T*)> d = DebugDelete()) : ptr(up), refCount(new std::size_t(1)), deleter(d) { } shared_pointer(const shared_pointer& sp): ptr(sp.ptr), refCount(sp.refCount), deleter(sp.deleter) { ++*refCount; } //! move constructor shared_pointer(shared_pointer&& sp) noexcept; //! copy assignment shared_pointer& operator =(const shared_pointer& rhs); //! move assignment shared_pointer& operator =(shared_pointer&& rhs) noexcept; //! conversion operator operator bool() const { return ptr ? true : false; } //! dereference T& operator* () const { return *ptr; } //! arrow T* operator->() const { return & this->operator *(); } //! return useCount std::size_t use_count() const { return *refCount; } //! get the underlying pointer T* get() const noexcept { return ptr; } //! check if the unique user bool unique() const noexcept { return *refCount == 1; } //! swap void swap( shared_pointer& rhs) { ::swap(*this, rhs); } //! if unique user, free the object pointed to void reset() noexcept { decrement_n_destroy(); } //! make prt point where p pointing and create a new coount for it void reset(T* p) { if(ptr != p) { decrement_n_destroy(); ptr = p; refCount = new std::size_t(1); } } //! reset to point where p is pointing and change deleter to d. void reset(T *p, const std::function<void(T*)>& d) { reset(p); deleter = d; } //! destructor ~shared_pointer() { decrement_n_destroy(); } private: //! data structure T* ptr = nullptr; std::size_t* refCount = new std::size_t(0); std::function<void(T*)> deleter {DebugDelete()}; void decrement_n_destroy(); }; template <typename T> inline void swap(shared_pointer<T>& lhs, shared_pointer<T>& rhs) { using std::swap; swap(lhs.ptr, rhs.ptr); swap(lhs.refCount, rhs.refCount); swap(lhs.deleter, rhs.deleter); } //! move constructor template<typename T> inline shared_pointer<T>::shared_pointer(shared_pointer&& sp) noexcept: ptr(sp.ptr), refCount(sp.refCount), deleter(std::move(sp.deleter)) { sp.ptr = nullptr; sp.refCount = nullptr; } //! copy assignment template<typename T> inline shared_pointer<T>& shared_pointer<T>::operator =(const shared_pointer& rhs) { ++*rhs.refCount; decrement_n_destroy(); ptr = rhs.ptr; refCount = rhs.refCount; deleter = rhs.deleter; return *this; } //! move assignment template<typename T> inline shared_pointer<T>& shared_pointer<T>::operator =(shared_pointer&& rhs) noexcept { decrement_n_destroy(); ::swap(*this, rhs); std::cout << "shared_pointer::move=\n"; return *this; } template <typename T> inline std::ostream& operator <<(std::ostream& os, shared_pointer<T> p) { os << p.get(); return os; } template <typename T> inline void shared_pointer<T>::decrement_n_destroy() { if(ptr) { if (--*refCount == 0) { delete refCount; deleter(ptr); } refCount = nullptr; ptr = nullptr; } } #endif
#ifndef UNIQUE_POINTER_H #define UNIQUE_POINTER_H #include "DebugDelete.h" template<typename, typename> class unique_pointer; template<typename T,typename D> void swap(unique_pointer<T,D>& lhs, unique_pointer<T,D>& rhs); template <typename T, typename D = DebugDelete> class unique_pointer { friend void swap<T,D>(unique_pointer<T,D>& lhs, unique_pointer<T,D>& rhs); public: unique_pointer(const unique_pointer&) = delete; unique_pointer& operator = (const unique_pointer&) = delete; unique_pointer() = default; explicit unique_pointer(T* up): ptr(up) { } //! move constructor unique_pointer(unique_pointer&& up) noexcept : ptr(up.ptr) { up.ptr = nullptr; } //! move assignment unique_pointer& operator =(unique_pointer&& rhs) noexcept; //! std::nullptr_t assignment unique_pointer& operator =(std::nullptr_t n) noexcept; //! operator overloaded : * -> bool T& operator *() const { return *ptr; } T* operator ->() const { return & this->operator *(); } operator bool() const { return ptr ? true : false; } //! return the underlying pointer T* get() const noexcept { return ptr; } //! swap member using swap friend void swap(unique_pointer<T, D> &rhs) { ::swap(*this, rhs); } //! free and make it point to nullptr or to p's pointee. void reset() noexcept { deleter(ptr); ptr = nullptr; } void reset(T* p) noexcept { deleter(ptr); ptr = p; } //! return ptr and make ptr point to nullptr. T* release(); ~unique_pointer() { deleter(ptr); } private: T* ptr = nullptr; D deleter = D(); }; //! swap template<typename T, typename D> inline void swap(unique_pointer<T,D>& lhs, unique_pointer<T,D>& rhs) { using std::swap; swap(lhs.ptr, rhs.ptr); swap(lhs.deleter, rhs.deleter); } //! move assignment template<typename T, typename D> inline unique_pointer<T,D>& unique_pointer<T,D>::operator =(unique_pointer&& rhs) noexcept { if(this->ptr != rhs.ptr) { deleter(ptr); ptr = nullptr; ::swap(*this, rhs); } return *this; } //! std::nullptr_t assignment template<typename T, typename D> inline unique_pointer<T,D>& unique_pointer<T,D>::operator =(std::nullptr_t n) noexcept { if(n == nullptr) { deleter(ptr); ptr = nullptr; } return *this; } template<typename T, typename D> inline T* unique_pointer<T,D>::release() { T* ret = ptr; ptr = nullptr; return ret; } #endif
练习16.39
#include <iostream> template <typename T> int compare(const T &v1, const T &v2) { if (v1 < v2) return -1; if (v2 < v1) return 1; return 0; } int main() { std::cout << compare<std::string>("sss","aaa") << "\n"; }
template<typename T> auto sum(T lhs, T rhs) -> decltype( lhs + rhs) { return lhs + rhs; }
#include <iostream> #include <memory> void func_lvalue(std::string& lhs, std::string& rhs) { lhs = "Wang\n"; rhs = "Alan\n"; } void func_rvalue(int&& lhs, int&& rhs) { //! allocate enough space std::allocator<int> alloc; int* data(alloc.allocate(3)); //! move into the spaced newly allocated alloc.construct(data , lhs); alloc.construct(data +1 , 0); alloc.construct(data +2 , rhs); //! print for (auto p = data; p != data + 3; ++p) std::cout << *p << "\n"; //! destroy and deallocation for (auto p = data +3; p != data; ) alloc.destroy(--p); alloc.deallocate(data,3); } template<typename F, typename T1, typename T2> void flip(F f, T1&& t1, T2&& t2) { f(std::forward<T2>(t2), std::forward<T1>(t1)); } int main() { //! test for lvalue reference /* std::string s1, s2; flip(func_lvalue, s1, s2); std::cout << s1 << s2; */ //! test for rvalue reference flip(func_rvalue, 99,88); }
#include <iostream> template<typename T,typename ...Args> void foo(T t,Args ...args) { std::cout << sizeof...(Args) << std::endl; std::cout << sizeof...(args) << std::endl; } int main() { foo(1,2); foo(1,23,4,5,6); }
#include <iostream> class Foo {}; template<typename T> std::ostream& print(std::ostream& os, const T& t) { return os << t; } template<typename T, typename... Args> std::ostream& print(std::ostream &os, const T &t, const Args&... rest) { //! print the first argument os << t << ","; //! recursive call; print the other arguments return print(os,rest...); } int main() { //print(std::cout, 1); print(std::cout, 1,2); //print(std::cout, 1,2,3,4,"sss"); //print(std::cout,foo,bar); }
#include <iostream> #include <memory> #include <sstream> template <typename T> std::string debug_rep(const T& t); template <typename T> std::string debug_rep(T* p); std::string debug_rep(const std::string &s); std::string debug_rep(char* p); std::string debug_rep(const char *p); template<typename T> std::string debug_rep(const T& t) { std::ostringstream ret; ret << t; return ret.str(); } template<typename T> std::string debug_rep(T* p) { std::ostringstream ret; ret << "pointer: " << p; if(p) ret << " " << debug_rep(*p); else ret << " null pointer"; return ret.str(); } std::string debug_rep(const std::string &s) { return '"' + s + '"'; } std::string debug_rep(char *p) { return debug_rep(std::string(p)); } std::string debug_rep(const char *p) { return debug_rep(std::string(p)); } template<typename T> std::ostream& print(std::ostream& os, const T& t) { return os << t; } template<typename T, typename... Args> std::ostream& print(std::ostream &os, const T &t, const Args&... rest) { os << t << ","; return print(os,rest...); } template<typename... Args> std::ostream& errorMsg(std::ostream& os, const Args... rest) { return print(os,debug_rep(rest)...); } int main() { errorMsg(std::cout, 1,2,3,4,9.0f,"sss","alan"); }
#include <iostream> #include <memory> template <typename T, typename ... Args> std::shared_ptr<T> wy_make_shared(Args&&...); int main() { auto p = wy_make_shared<int>(42); std::cout << *p << std::endl; auto p2= wy_make_shared<std::string>(10,'c'); std::cout << *p2 << std::endl; } template <typename T, typename ... Args> inline std::shared_ptr<T> wy_make_shared(Args&&... args) { std::shared_ptr<T> ret( new T(std::forward<Args>(args)...)); return ret; }
#include <iostream> #include <vector> #include <cstring> template<typename T> std::size_t count(const std::vector<T>& vec, T value); template<> std::size_t count (const std::vector<const char*> &vec, const char* value); int main() { //ex16.63 /* std::vector<int> vi = {1,2,3,4,5,6,7,1,1,1,1}; std::vector<double> vd = {1.1,1.1,2.3,4}; std::cout << count(vd, 1.1); */ //ex16.64 std::vector<const char*> vcc = {"alan","alan","alan","alan","moophy"}; std::cout << count(vcc, "alan"); return 0; } template<typename T> std::size_t count(const std::vector<T>& vec, T value) { std::size_t count = 0; for(auto& item : vec) count += (item == value)? 1 : 0 ; return count; } template<> std::size_t count (const std::vector<const char*> &vec, const char* value) { std::size_t count = 0; for(auto& item : vec) count += (strcmp(item,value) == 0)? 1 : 0; return count; }