У меня есть шаблон для функции, которая принимает аргумент итератора вывода. Как я могу использовать static_assert
, чтобы проверить, что экземпляр использует соответствующий итератор? (Т.е., так что он является выходным итератора, и что он присваивает элементы правильного типа.)Как static_assert можно использовать для проверки типа элемента аргумента итератора на шаблонную функцию?
#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
}
Использование 'iterator_traits :: value_type'. Вы должны использовать 'iterator_traits' для вашей текущей проверки для размещения типа без вложенного типа' iterator_category' (не уверен, что это возможно для OutputIterator). Я также утверждаю, что вы должны использовать 'is_base_of' вместо' is_same' для проверки категории итератора. Ваш код должен по-прежнему работать, если кто-то передал вам более утонченную категорию итераторов, которая по-прежнему соответствует всем требованиям 'OutputIterator' (хотя сегодня такого типа в stdlib нет). –
Praetorian
'OutputIterator' должны поддерживать только' * r = o', а не 'r = o'. Тот факт, что для некоторых стандартных выходных итераторов библиотеки операция разыменования является no-op, является детальностью реализации этих итераторов, и вы не должны полагаться на это в общем коде. Проверка на 'std :: output_iterator_tag' также не является отличной идеей в целом; многие измененные итераторы будут иметь другой тег. –
@Praetorian Это не делает то, что вы хотите. Для многих 'OutputIterator', 'iterator_traits :: value_type' является' void'. –