如何在C++
中要求并检查参数是否为某个概念?
例如,random_shuffle
标题中的algorithm
函数要求其参数为RandomAccessIterators:
template<typename _RandomAccessIterator>
inline void
random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last)
{
// concept requirements
__glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
_RandomAccessIterator>)
__glibcxx_requires_valid_range(__first, __last);
if (__first != __last)
for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i)
std::iter_swap(__i, __first + (std::rand() % ((__i - __first) + 1)));
}
我想我不能在我自己的代码中使用这些__glibcxx_function_requires
等?他们是如何工作的?你在代码中检查这样的东西吗?
答案 0 :(得分:6)
Boost有一个库。与确定如何使用STL实施者一起攻击的版本相比,它可能更容易,也更有文档记录。
http://www.boost.org/doc/libs/1_40_0/libs/concept_check/concept_check.htm
答案 1 :(得分:2)
除非您定义_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算法有评论,我本可以更快地想出来。
有一点是你不一定需要这些检查。如果不满足要求,代码将无法编译。在我看来,一个简单的“没有匹配的运算符&lt;”可能比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&amp;,std :: _ List_iterator&amp;,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的概念检查没有它们的位置。