More Exceptional C++ 读书笔记

来源:互联网 发布:西班牙语字典推荐 知乎 编辑:程序博客网 时间:2024/05/26 05:51
Item 1 Switching Streams

(1): 多考虑易读性,避免编写过渡简洁但是不易懂,不易维护的代码;

记个相当简洁的流切换代码:
(argc > 2 ? ofstream(argv[2], ios::out|ios::binary) : cout ) << (argc > 1 ? ifstream(argv[1], ios::in|ios::binary) :  cin).rdbuf();


(2): 设计函数时
a: 优先考虑可扩展性,但对于一个简单问题的处理不应当采用过渡设计和过于专一的发放,要权衡这两者;

b: 多考虑封装,将问题分离开;只要可能,就应当让一段代码只拥有一个功能;


Item 2Predicates, Part 1: What remove() Removes;

(1):  remove()删除在[first,last)范围内的所有value 实例remove()以及remove_if()并不真正地
把匹配到的元素从容器中清除即容器的大小保留不变而是每个不匹配的元素依次被赋
值给从first 开始的下一个空闲位置上返问的ForwardIterator 标记了新的元素范围的下一个
位置例如考虑序列{0,1,0,2,0,3,0,4} 假设我们希望删除所有的0 则结果序列是
{1,2,3,4,0,3,0,4} 1 被拷贝到第一个位置上2 被拷贝到第二个位置上3 被拷贝到第三个位
置上4 被拷贝到第四个位置上返回的ForwardIterator 指向第五个位置上的0 典型的做法
是该iterator 接着被传递给erase() 以便删除无效的元素内置数组不适合于使用remove()
和remove_if()算法因为它们不能很容易地被改变大小由于这个原因对于数组而言
remove_copy()和remove_copy_if()是更受欢迎的算法.


(2):   一个remove_nth的正确实现:
template<FwdIter>
FwdIter remove_nth(FwdIter first, FwdIter last, size_t  n)
{
assert(distance(first, last) >= n);
advance(first, n);
if(first != last)
{
FwdIter dest = first;
return copy(++first, last, dest);
}
return last;
}

(3): 多考虑泛型算法 + 断言的形式,而不是重新实现一个泛型算法;

(4): 所谓断言是一个函数指针或者函数对象, 返回一个bool,泛型算法依据返回值执行相应操作;

(5): stateful 断言;不依赖泛型算法传递对象到operator(),而是根据调用次数独立的自动更新函stateful断言内的数据;

(6): stateful断言对泛型算法的要求: 
a: 泛型算法必须用一个恒定的函数对象,而不能用其拷贝来作运算;
b: 泛型算法必须把函数对象按照已知的顺序提交给每一个容器中的元素;

c:  一个安全的stateful断言:



template<class T>
class CountedPtr
{
private:
class Impl
{
public:
Impl(T* pp) : p(pp), refs(1) {}
~Impl() { delete p; }
T* p;
size_t refs;
};
Impl *impl_;
public:
explicit CountedPtr(T *p) : impl_(new Impl(p) ) {}
~CountedPtr() { Decrement(); }
CountedPtr(const CountedPtr &other) : impl_(other.impl_) { Increment(); }
CountedPtr& operator=(const CountedPtr& othher)
{
if(impl_ != other.impl_)
{
Decrement();
impl_ = other.impl_;
Increment();
}
return *this;
}

T* operator->() const { return impl_->p;}
T& operator*() const { return *(impl_->p); }
private:
void Dcrement()
{
if(--(impl_->refs) == 0)
delete impl_;
}

void Increment() { ++(impl_->refs); }
};


class FlagNthImpl
{
public:
FlagNthImpl(size_t nn) : i(0), n(nn) {}
size_t i;
const size_t n;
};

class FlagNth
{
public:
FlagNth(size_t n) : pimpl_(new FlagNthImpl(n)) {}
template<typename T>
bool operator() (const T&)
{
return ++(pimpl_->i) == pimpl_->n;
}
private:
CountedPtr<FlagNthImpl> pimpl_;
};



Item 4 Extensible Template: Via Inheritance or Traits ?

(1): 什么是Traits class
      一个封装了一组类型和函数供模板类或者模板函数对某个被操作对象做偏特化的类;

(2): 限制类

    例如判定某个类里面是否存在某个函数;
可以

template<class T>
class HasClone
{
public:
static void Constraints()
{
T* (T::*test)() const = &T::Clone;
test;
}
HasClone() { void (*p)() = Constraints; }
};



template<class D, class B>
class IsDerivedFrom
{
class No { };
class Yes { No no[2]; };
static Yes Test(B*);
static No  Test(...);
static void Constraints(D *pd) { B *pb = pd; pb = pd; }

public:
enum { Is = sizeof(Test(static_cast<D*>(0))) == sizeof(Yes) };
IsDerivedFrom() { void (*test)(D*) = Constraints; }
};

如果D是派生自B, 那么这个类的Is值为sizeof(Yes),否则为 sizeof(No);如果class XX : public IsDerivedFrom<B, D>的话,如果
D派生自B,那么将编译通过,否则无法编译通过;

另外可以用这个类的Is来当作模板偏特化的参数,来给某个模板类两个版本,例如

template<class T, size_t>
class X {};
template<>
class X<T, 0> {};
template<>
class X<T, 1> {};

void f()
{
X<T, IsDerivedFrom<D, B>::Is> xx;
}


(3): 关于如何实现Traits类:
a:首先设计一个常规的Traits
例如:
template<class T>
class Traits
{
public:
static T* Clone(const T* p) { return new T(*p); }
};

b: 然后是对某个类进行偏特化
template<>
class Traits<MyCloneable>
{
public:
static MyCloneable* Clone(const MyCloneable* p) { return p->Clone(); }
};

0 0
原创粉丝点击