[英]How can static_assert be used to check element type of iterator argument to templated function?
I have a template for a function that takes an output iterator argument. 我有一个带有输出迭代器参数的函数模板。 How can I use
static_assert
to check that an instantiation uses an appropriate iterator? 如何使用
static_assert
检查实例化是否使用适当的迭代器? (Ie, both that it is an output iterator, and that it assigns elements of the correct type.) (即,它既是输出迭代器,又分配了正确类型的元素。)
#include <iostream>
#include <list>
#include <set>
template <class OutputIter>
void add_ints ( OutputIter iter )
{
static_assert ( something_goes_here,
"Arg must be an output iterator over ints" );
*iter++ = 1;
*iter++ = 2;
*iter++ = 3;
}
main()
{
// Insert iterator will add three elements.
std::set<int> my_set;
add_ints ( std::inserter ( my_set, my_set.end() ) );
for ( int i : my_set ) std::cout << i << "\n";
// Non-insert iterator will overwrite three elements.
std::list<int> my_list ( { 0, 0, 0 } );
add_ints ( my_list.begin() ) );
for ( int i : my_list ) std::cout << i << "\n";
#if 0
// Want nice compile error that container elements are not ints.
std::set<std::string> bad_set;
add_ints ( std::inserter ( bad_set, bad_set.end() ) );
#endif
#if 0
// Want nice compile error that argument is not an iterator.
class Foo {} foo;
add_ints ( foo );
#endif
}
OutputIterator
s are not required to have value types; OutputIterator
不需要具有值类型; their value_type
may well be void
, and in fact is void
for the purely output iterators from the standard library. 它们的
value_type
可能是void
,实际上对于标准库中纯输出的迭代器而言,它们是void
的。
In your original question you checked for output_iterator_tag
, but you should not. 在最初的问题中,您检查了
output_iterator_tag
,但您没有这样做。 There are plenty of perfectly mutable iterators that have a different category. 有很多完全可变的迭代器具有不同的类别。
std::vector<int>::iterator
's category is random_access_iterator_tag
, for instance. std::vector<int>::iterator
的类别是random_access_iterator_tag
。
Instead, check the well-formed-ness of the applicable expressions directly. 而是直接检查适用表达式的格式正确性。 All
Iterator
s must support *r
and ++r
, and in addition OutputIterator
s must support *r = o
, r++
, and *r++ = o
, so: 所有
Iterator
必须支持*r
和++r
,此外OutputIterator
s还必须支持*r = o
, r++
和*r++ = o
,因此:
template<class...>
struct make_void { using type = void; };
template<class... Ts>
using void_t = typename make_void<Ts...>::type;
template<class Iter, class U, class = void>
struct is_output_iterator_for : std::false_type {};
template<class Iter, class U>
struct is_output_iterator_for<
Iter, U,
void_t<decltype(++std::declval<Iter&>()),
decltype(*std::declval<Iter&>() = std::declval<U>()),
decltype(*std::declval<Iter&>()++ = std::declval<U>())>> : std::true_type {};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.