除非您定义 _GLIBCXX_CONCEPT_CHECKS,否则这些宏将被定义。所以我试图编译这两种方式:
#include <list>
#include <algorithm>
int main()
{
std::list<int> li;
std::random_shuffle(li.begin(), li.end());
}
没有概念检查:8 行错误 - 哪个实例化,在哪里,不匹配运算符。一切都清楚。
使用概念检查:相同的错误 + 50 行左右的“从这里实例化”乱码以“错误:从 'std::bidirectional_iterator_tag' 转换为非标量类型 'std::random_access_iterator_tag' 请求”结尾。嗬!如果对 random_shuffle 算法有评论,我本可以更快地弄清楚这一点。
一件事是您不一定需要这些检查。如果不满足要求,代码将无法编译。在我看来,一个简单的“不匹配的运算符<”可能比 50 行胡言乱语更清楚(用晦涩的措辞)“功能需要小于可比的概念”。
如果您想要这些检查(对于诸如 random_shuffle 之类的东西),一种方法是将调用转发到另一个也接受正确迭代器标记的函数:
#include <list>
#include <algorithm>
#include <iterator>
namespace detail {
template <class Iter>
void shuffle(Iter first, Iter last, std::random_access_iterator_tag)
{
if (first != last)
for (Iter i = first + 1; i != last; ++i)
std::iter_swap(i, first + (std::rand() % ((i - first) + 1)));
}
}
template <class Iter>
void shuffle(Iter first, Iter last)
{
detail::shuffle(first, last, typename std::iterator_traits<Iter>::iterator_category());
}
int main()
{
std::list<int> li;
shuffle(li.begin(), li.end());
}
产生一条很好的消息:“没有匹配函数调用'shuffle(std::_List_iterator&, std::_List_iterator&, std::bidirectional_iterator_tag)'”
如果你想成为 über-nice,你可以添加一个模板化的重载,它在编译时断言(static_assert 与 C++0x 一起提供):
template <class Iter, class Tag>
void shuffle(Iter, Iter, Tag )
{
//test some template-dependent expression that is always false
//to avoid it from firing unless the function is instantiated
static_assert(sizeof(Tag) == 0, "shuffle requires random access iterators");
}
并不是说 boost 的概念检查没有它们的位置。