double sum(double array[], int n)
{
double result = 0;
for (int i = 0; i < n; ++i)
result = result + array[i];
return result;
}
这是一个简单的求加的函数。
template<typename T>
T sum(T array[], int n)
{
T result = 0;
for (int i = 0; i < n; ++i)
result = result + array[i];
return result;
}
第一步,是模板化。
struct pod
{
int i;
};
int main()
{
pod values[3] = { {1}, {2}, {3} };
sum(values, 3);
return 0;
}
第二步是测试。。。
这个会出问题么?当然会咯。。所以说。。。我们需要引入概念模型。。
所谓的概念模型就是类型检查。。,当引入某个模板的时候,检查它的参数符合不符合一组接口。。。。。。
#include <boost/concept_check.hpp>
template <class RandomAccessIter>
void stable_sort(RandomAccessIter first, RandomAccessIter last)
{
function_requires< RandomAccessIteratorConcept<RandomAccessIter> >();
//... bla bla bla......
}
上面的代码,在说。。如果我们的 first和last 不符合 function_requires函数。。就会报错。
template <class Concept>
inline void function_requires(mpl::identity<Concept>* = 0)
{
#if !defined(NDEBUG)
void (Concept::*x)() = BOOST_FPTR Concept::constraints;
ignore_unused_variable_warning(x);
#endif
}
这个代码解释了上面的function_requires的样子。注意其中的 inline 和 ! if !defined(NDEBUG)。
而且,其中的void(Concept::*x)()是一个在类Concept内的指针类型,指向了Concept中的constriants;
这就是它的巧妙之处,我们仅仅去取一个函数的地址。而这个函数的参数类型在以下地方给出。
template <class TT>
struct RandomAccessIteratorConcept
{
void constraints() {
function_requires< BidirectionalIteratorConcept<TT> >();
function_requires< ComparableConcept<TT> >();
#ifndef BOOST_NO_STD_ITERATOR_TRAITS
typedef typename std::iterator_traits<TT>::iterator_category C;
function_requires< ConvertibleConcept< C,
std::random_access_iterator_tag> >();
typedef typename std::iterator_traits<TT>::reference R;
#endif
i += n; // require assignment addition operator
i = i + n; i = n + i; // require addition with difference type
i -= n; // require assignment subtraction operator
i = i - n; // require subtraction with difference type
n = i - j; // require difference operator
(void)i[n]; // require element access operator
}
TT a, b;
TT i, j;
#ifndef BOOST_NO_STD_ITERATOR_TRAITS
typename std::iterator_traits<TT>::difference_type n;
#else
std::ptrdiff_t n;
#endif
};
至此,结束。
疑点有很多:
1.为什么要这样做?
答案:因为原来的出错信息很模糊。。现在可以准确定位。。。
2.不执行函数就能确定函数的执行过程?
3.关于如何check.;;据说是利用虚函数机制,进行check?constraints是个虚函数???