Tip 21. Define a Visual Selection
從普通模式切回模式:
v 啟動字符的可視模式
V 啟動字行的可視模式
<C-v> 啟動塊狀的可視模式
gv 重選上次所選擇的區域
在可視模式:
<Esc> / <C-[> 切回普通模式
o 切換高亮區的活動端
template<typename IterT>
void workWithIterator(IterT iter) {
typedef typename std::iterator_traits::value_type value_type;
value_type temp(*iter);
...
}
class CompanyA {
public:
...
void sendCleartext(const std::string& msg);
void sendEncrypted(const std::string& msg);
...
};
class CompanyB {
public:
...
void sendCleartext(const std::string& msg);
void sendEncrypted(const std::string& msg);
...
};
class MsgInfo { ... }; // 用來保存資訊,以產生訊息
template
class MsgSender {
public:
...
void sendClear(const MsgInfo& info) {
std::string msg;
... // 根據 info,產生 msg
Company c;
c.sendCleartext(msg);
}
void sendSecret(const MsgInfo& info) {
std::string msg;
Company c;
c.sendEncrypted(msg);
}
};
template
class LoggingMsgSender : public MsgSender{
public:
...
void sendClearMsg(const MsgInfo& info) {
... // 紀錄傳送前的 log
sendClear(info);
// 呼叫 base class function,尚無法通過 compile
... // 紀錄傳送後的 log
}
...
};
class CompanyZ { // 不提供 sendCleartext function
public:
...
void sendEncrypted(const std::string& msg);
...
};
template<> // MsgSender total template specialization
class MsgSender<CompanyZ> {
public:
...
void sendSecret(const MsgInfo& info) {
...
}
};
template
class LoggingMsgSender : public MsgSender{
public:
...
void sendClearMsg(const MsgInfo& info) {
... // 紀錄傳送前的 log
this->sendClear(info); // 假設 sendClear 將被繼承
... // 紀錄傳送後的 log
}
...
};
template
class LoggingMsgSender : public MsgSender{
public:
...
void sendClearMsg(const MsgInfo& info) {
using MsgSender::sendClear;
... // 紀錄傳送前的 log
sendClear(info); // 假設 sendClear 位於 base class 內
... // 紀錄傳送後的 log
}
...
};
template
class LoggingMsgSender : public MsgSender{
public:
...
void sendClearMsg(const MsgInfo& info) {
... // 紀錄傳送前的 log
MsgSender::sendClear(info); // 假設 sendClear 將被繼承
... // 紀錄傳送後的 log
}
...
};
LoggintMsgSenderzMsgSender;
MsgInfo msgData;
...
zMsgSender.sendClearMsg(msgData); // 無法通過 compile
template<typename T, std::size_t n>
class SquareMatrix {
public:
...
void invert(); // 逆反矩陣
};
SquareMatrixsm1;
...
sm1.invert(); // 呼叫 SquareMatrix::invert
SquareMatrixsm2;
...
sm2.invert(); // 呼叫 SquareMatrix::invert
template<typename T>
class SquareMatrixBase {
protected:
...
void invert(std::size_t matrixSize); // 逆反矩陣
};
template<typename T, std::size_t n>
class SquareMatrix : private SquareMatrixBase<T> {
private:
using SquareMatrixBase::invert; // 避免遮掩 base 版的 invert
public:
...
void invert(s) { this->invert(n) };
// 避免遮掩 templatized base class 內的 function
};
template<typename T>
class SquareMatrixBase {
protected:
SquareMatrixBase(std::size_t n, T* pMem)
: size(n)
, pData(pMem) {
}
void setDataPtr(T* ptr) { pData = ptr; }
...
private:
std::size_t size; // 矩陣大小
T* pData; // pointer,指向矩陣內容
};
template<typename T, std::size_t n>
class SquareMatrix : private SquareMatrixBase<T> {
public:
SquareMatrix()
: SquareMatrixBase(n, data)
, pData(new T[n*n]) {
this->setDataPtr(pData.get());
}
...
private:
boost::scoped_arraypData; // 祥見條款 13
};
class Top { ... };
class Middle : public Top { ... };
class Bottom : public Middle { ... };
Top* pt1 = new Middle; // 將 Middle* 轉換為 Top*
Top* pt2 = new Bottom; // 將 Bottom* 轉換為 Top*
const Top* pct2 = pt1; // 將 Top* 轉換為 const Top*
template<typename T>
class SmartPtr {
public: // smart pointer 通常以
explicit SmartPtr(T* realPtr); // 內建原始 pointer 完成初始化
...
};
SmartPtr<Top> pt1 = SmartPtr<Middle>(new Middle);
SmartPtr<Top> pt2 = SmartPtr<Bottom>(new Bottom);
SmartPtr<const Top> pct2 = pt1;
template<typename T>
class SmartPtr {
public:
template<typename U> // member template
SmartPtr (const SmartPtr<U>& other); // 為了生成 copy constructor
...
};
template<typename T>
class SmartPtr {
public:
template<typename U>
SmartPtr (const SmartPtr<U>& other) // 以 other 的 heldPtr
: heldPtr(other.get()) { ... } // 初始化 this 的 heldPtr
T* get() const { return heldPtr; }
...
private:
T* heldPtr; // 這個 SmartPtr 持有的內建原始 pointer
};
template<class T>
class shared_ptr {
public:
shared_ptr(shared_ptr const& r); // copy constructor
template<class Y> // generalized copy constructor
shared_ptr(shared_ptr<Y> const& r);
shared_ptr& operator=(shared_ptr const& r); // copy assignment
template<class Y> // generalized copy assignment
shared_ptr& operator=(shared_ptr<Y> const& r);
...
};
template<typename T>
class Rational {
public:
Rational(const T& numerator = 0, const T& denominator = 1);
const T numerator() const;
const T denominator() const;
...
};
template<typename T>
const Rational<T> operator* (const Rational<T>& lhs,
const Rational<T>& rhs) {
...
}
Rational<int> oneHalf(1, 2);
Rational<int> result = oneHalf * 2; // 錯誤,無法通過 compile
template<typename T>
class Rational {
public:
...
friend const Rational operator*(const Rational& lhs,
const Rational& rhs);
// 在 class template 內,template 名稱可被用來做為
//「template 和其參數」的簡略表達方式
};
template<typename T>
const Rational<T> operator* (const Rational<T>& lhs,
const Rational<T>& rhs) {
...
}
template<typename T>
class Rational {
public:
...
friend const Rational operator*(const Rational& lhs,
const Rational& rhs) {
return Rational(lhs.numerator() * rhs.umerator() ,
lhs.denominator() * rhs.denominator());
}
};
template<typename T> class Rational; // 宣告 Rational template
template<typename T> // 宣告 helper template
class Rational<T> doMultiply(const Rational& lhs,
const Rational& rhs);
template<typename T>
class Rational {
public:
...
friend const Rational operator*(const Rational& lhs,
const Rational& rhs) {
return doMultiply(lhs, rhs); // 令 friend 呼叫 helper
}
};
template<typename T>
const Rational<T> doMultiply(const Rational& lhs,
const Rational& rhs) {
return Rational(lhs.numerator() * rhs.umerator() ,
lhs.denominator() * rhs.denominator());
}
template<typename IterT, typename DistT>
void advance(IterT& iter, DistT d);
// 將 iterator 向前移動 d 單位,如果 d < 0 則向後移動
struct input_iterator_tag {};
struct output_iterator_tag {};
struct forward_iterator_tag : public input_iterator_tag {};
struct bidirectional_iterator_tag : public forward_iterator_tag {};
struct random_access_iterator_tag : public bidirectional_iterator_tag {};
template<typename IterT, typename DistT>
void advance(IterT& iter, DistT d) {
if (iter is a random access iterator) {
iter += d; // 針對 random access iterator 使用算術運算
} else {
if (d >= 0) { while (d--) ++iter; } // 其它 iterator
else { while (d++) --iter; } // 則反覆呼叫 ++ 或 --
}
}
template<typename IterT> // template,用來處理
struct iterator_traits; // iterator 的相關資訊
template < ... > // 略而未寫 template 參數
class deque {
public:
class iterator {
typedef random_access_iterator_tag iterator_category;
};
...
};
template < ... >
class list {
public:
class iterator {
typedef bidirectional_iterator_tag iterator_category;
};
...
};
template <typename IterT>
struct iterator_traits {
typedef typename IterT::iterator_category iterator_category;
};
template <typename IterT> // partial template specialization
struct iterator_traits<IterT*> { // 針對 built-in pointer
typedef random_access_iterator_tag iterator_category;
};
template<typename IterT, typename DistT>
void advance(IterT& iter, DistT d) {
if (typeid(typename std::iterator_traits<IterT>::iterator_category)
== typeid(std::random_access_iterator_tag)) {
...
}
template<typename IterT, typename DistT>
void doAdvance(IterT& iter, DistT d, std::random_access_iterator_tag) {
iter += d;
}
template<typename IterT, typename DistT>
void doAdvance(IterT& iter, DistT d, std::bidirectional_iterator_tag) {
if (d >= 0) { while (d--) ++iter; }
else { while (d++) --iter; }
}
template<typename IterT, typename DistT>
void doAdvance(IterT& iter, DistT d, std::input_iterator_tag) {
if (d < 0) {
throw std::out_of_range("Negative distance");
}
while (d--) ++iter;
}
//
template<typename IterT, typename DistT>
void advance(IterT& iter, DistT d) {
doAdvance(iter, d,
typename std::iterator_traits<IterT>::iterator_cagetory()
);
}
std::list<int>::iterator iter;
...
advance(iter, 10); // 無法通過 compile
void advance(std::list<int>::iterator& iter, int d) {
if (typeid(std::iterator_traits<:list>::iterator_category
== typeid(std::random_access_iterator_tag)) {
iter += d; // 錯誤
} else {
if (d >= 0) { while (d--) ++iter; }
else { while (d++) --iter; }
}
}
template<unsigned n>
struct Factorial {
enum { value = n * Factorial::value };
};
template<>
struct Factorial<0> {
enum { value = 1 };
};
int main() {
std::cout << Factorial<5>::value << std::endl; // 120
std::cout << Factorial<10>::value << std::endl; // 3628800
return 0;
}