通过普通参数(此处是参数T)来表达模板参数之间必要的关系,很不幸没有强大的表现能力,导致我们添加模板参数,并且间接地(无法直接地)表达需求。例如,上面的例子不能说明把*first的结果作为参数传递给pred一定可行。其实,它说明的是Forward_iterator和Predicate共享了一个模板参数类型。为了处理这类问题,我们正在研究直接表达模板参数之间关系的可能性。例如:
template<Forward_iterator In, Predicate Pred>
where (assignable<In::value_type, Pred::argument_type>)
In find_if(In first, In last, Pred pred);
概念的一种可能的表达方式是直接支持我们过去使用的约束类这种表达方式。例如,我们采用如下的方式来定义前面例子中使用的Forward_iterator:
template <class T> concept Forward_iterator {
// 参数化的概念
Forward_iterator a;
++a; a++; // 可以增加
Forward_iterator b = a; b = a; // 可以复制
*b = *a; // 可以废除和复制结果
T x = *a; *a = x; // 可以认为结果是T类型的
};
concept Forward_iterator { // 概念没有用参数表示
Forward_iterator a;
++a; a++; //可以增加
Forward_iterator b = a; b = a; //可以复制
*b = *a; // 可以废除和复制结果
};
int x = find_if(1,2,Less_than<int>(7));
这是不合格的,因为1和2是int型的,而int不支持*。如果我们使用参数化的概念设计,它也是不合格的,因为int不是一个能够与Forward_iterator<T>匹配的参数化类型。另一方面,看下面的例子:void f(vector<int>& v, int* p, int n)
{
vector<int>::iterator q = find_if(v.begin(),v.end(),Less_than<int>(7));
int* q2 = find_if(p,p+n,Less_than<int>(7));
// …
}
现在以概念和它与其它语言中相似的构造之间可能的关系为主题的论文很广泛。Matt Austern、Jaako J?rvi、Mich Marcus、Gabriel Dos Reis、Jeremy Siek、Alex Stepanov和我都活跃在这个设计问题的领域。
2、泛化的初始化器
C++的一个基本的想法是"对用户定义类型的支持如同内建类型一样好"。但是,看看下面的情形:
double vd[ ] = { 1.2, 2.3, 3.4, 4.5, 5.6 };
vector<double> v(vd, vd+5);
vector<double> v;
v.push_back(1.2);
v.push_back(2.3);
v.push_back(3.4);
v.push_back(4.5);
v.push_back(5.6);
vector<double> v = { 1.2, 2.3, 3.4, 4.5, 5.6 };
或者vector<double> v ({ 1.2, 2.3, 3.4, 4.5, 5.6 });
由于参数传递是在初始化过程中定义的,因此对于带有vector的函数来说,这也是可行的:void f(const vector<double>& r);
// …
f({ 1.2, 2.3, 3.4, 4.5, 5.6 });
