Как определить, является ли тип итератором или const_iterator
Мне интересно, если есть способ проверить во время компиляции, является ли тип T некоторого типа итератора const_iterator, или нет. Есть ли разница в типах, которые определяют итераторы (value_type, pointer,...) между итераторами и константными итераторами?
Я хотел бы добиться чего-то вроде этого:
typedef std::vector<int> T;
is_const_iterator<T::iterator>::value // is false
is_const_iterator<T::const_iterator>::value // is true
Ответы
Ответ 1
С++ 03 Решение:
Как ни один из ответов кажется правильным, вот моя попытка, которая работает с GCC:
template<typename T>
struct is_const_pointer { static const bool value = false; };
template<typename T>
struct is_const_pointer<const T*> { static const bool value = true; };
template <typename TIterator>
struct is_const_iterator
{
typedef typename std::iterator_traits<TIterator>::pointer pointer;
static const bool value = is_const_pointer<pointer>::value;
};
Пример:
int main()
{
typedef std::vector<int>::iterator it_type;
typedef std::vector<int>::const_iterator const_it_type;
std::cout << (is_const_iterator<it_type>::value) << std::endl;
std::cout << (is_const_iterator<const_it_type>::value) << std::endl;
}
Вывод:
0
1
Онлайн-демонстрация: http://ideone.com/TFYcW
Ответ 2
Один метод, который работает, по крайней мере, на gcc, - через ссылку typedef:
struct true_type { };
struct false_type { };
template<typename T>
struct is_const_reference
{
typedef false_type type;
};
template<typename T>
struct is_const_reference<T const &>
{
typedef true_type type;
};
template<typename T>
struct is_const_iterator
{
typedef typename is_const_reference<
typename std::iterator_traits<T>::reference>::type type;
};
Вы можете проверить, работает ли это с помощью
inline bool test_internal(true_type)
{
return true;
}
inline bool test_internal(false_type)
{
return false;
}
template<typename T>
bool test(T const &)
{
return test_internal(typename is_const_iterator<T>::type());
}
bool this_should_return_false(void)
{
std::list<int> l;
return test(l.begin());
}
bool this_should_return_true(void)
{
std::list<int> const l;
return test(l.begin());
}
При достаточно высоком уровне оптимизации последние две функции должны быть уменьшены до return false;
и return true;
соответственно. По крайней мере, они делают для меня.
Ответ 3
C++ 11
template<class IT, class T=decltype(*std::declval<IT>())>
constexpr bool
is_const_iterator() {
return ! std::is_assignable <
decltype( *std::declval<IT>() ),
T
>::value;
}
Ответ 4
С С++ 11 новый стандартный заголовок <type_traits>
предоставляет std::is_const<T>
,
поэтому решение Nawaz можно упростить:
template<typename Iterator>
struct is_const_iterator
{
typedef typename std::iterator_traits<Iterator>::pointer pointer;
static const bool value =
std::is_const<typename std::remove_pointer<pointer>::type>::value;
};
Ответ 5
Это немного взломанно, потому что вам нужно передать T
сам, но он работает (специализация шаблона, g++ 4.4.5):
template<typename T, typename S>
struct is_const_iterator {
enum {
value = false
};
};
template<typename T>
struct is_const_iterator<T, typename T::const_iterator> {
enum {
value = true
};
};
Используйте это:
typedef std::vector<int> T;
is_const_iterator<T, T::iterator>::value //is false
is_const_iterator<T, T::const_iterator>::value //is true