1

Тема: iterator_category for references to pointer

Всім привіт.

Ітератор - тип даних, призначений для ітерування по елементах колекцій, і доступу до самих елементів.

Як визначити: чи є тип даних ітератором?
Найпростіший спосіб, це подивитися: чи визначена для типу категорія ітераторів: iterator_traits<>::iterator_category
Якщо визначена - це ітератор.

У свою чергу, iterator_traits керується вимогами до так званих легальних Ітераторів.

Тепер питання: чому шаблон iterator_traits<>::iterator_category не визначений для посилань на вказівники?

using ptr = std::iterator_traits<int*>::iterator_category; // ok
using ref_ptr = std::iterator_traits<int*&>::iterator_category; // fails

Посилання на звичайний покажчик на всі 100% відповідає вимогам до "легальних Ітераторів".

template<class T> void dtor(T v)
{
    v.~t();
}
 
int main()
{
    int v = 0;
    int* p = &v;
    int*& r1 = p;
    
    int*& r2 = p;      // CopyConstructible
    r2 = p;            // CopyAssignable
    dtor(r2);          // Destructible
    std::swap(r2, r1); // Swappable
 
    ++r2; // increment
    *r2;  // dereference
}

2 Востаннє редагувалося koala (17.09.2020 18:36:28)

Re: iterator_category for references to pointer

Ну взагалі виглядає логічним: посилання на ітератор - це не ітератор, це посилання. Так само як посилання на ціле число - це не ціле число.

#include <type_traits>
...
std::cout<<std::is_arithmetic<int>::value<<" "<<std::is_arithmetic<int&>::value<<std::endl;
1 0

А звідки таке питання виникло?

3

Re: iterator_category for references to pointer

А до чого тут посилання на ітератор?
Чи посилання на ціле число?
Мова йшла про *&

#include <type_traits>
...
std::cout << std::is_same_v<int&, int*&> << std::endl;
0

4 Востаннє редагувалося koala (17.09.2020 22:38:46)

Re: iterator_category for references to pointer

Бо ітератор - це узагальнення від вказівника. Вказівник є ітератором (п. 24.2.1 Стандарту); посилання на вказівник (чи інший ітератор) є посиланням на вказівник, а не вказівником.
О, спробую пояснити ще так: чи є int*& вказівником?

std::cout<<std::is_pointer<int*>::value<<" "<<std::is_pointer<int*&>::value<<std::endl;
1 0

Ні, не є. Вказівник є ітератором. Посилання на вказівник не є ані вказівником, ані ітератором.

5

Re: iterator_category for references to pointer

Питання не про вказівник, а про концепцію ітератора.
Що ж добре, ми з вами на 5 повідомленні дійшли висновку, що посилання на вказівник не є вказівником, це круто.
Проте, яке це все ще має відношення до мого питання?
Ок, перефразую питання:
до ітераторів є певні вимоги (по вашому ж посиланню) в голові теми я описала, що посилання цілком відповідає всім вимогам, тоді в чому різниця?

6

Re: iterator_category for references to pointer

koala написав:

Бо ітератор - це узагальнення від вказівника. Вказівник є ітератором (п. 24.2.1 Стандарту);

Лихо ви завернули, дослівний переклад слів стандарту не найкращий варіант :)
Може скластися враження, що вказівник та ітератор тотожні речі, хоча це не так.

Вказівник - це деякий вид ітератора і він навіть може використовуватися, як ітератор, проте у вказівника є деякі власні особливості, які не підпадають під концепцію ітераторів.

Ітератор - це швидше деяка спроба емуляції функціоналу моделі С вказівника. Тобто щось, що дуже схоже по функціоналу до вказівника, проте не один в один. Концепція ітераторів була придумана для того, щоб надати деякий "непрозорий" об'єкт, який би дозволяв переглядати певну колекцію об’єктів уніфіковано (завжди однаково), навіть незважаючи на те, що колекції можуть мати кардинально іншу внутрішню структуру.
Відповідно реалізація ітератора може бути й не через вказівник, про що і свідчить заборона на відповідне перетворення.

Naomi написав:

до ітераторів є певні вимоги

dtor(r2);          // Destructible

І справді є, проте схоже ви їх читали поміж рядками?
https://i.ibb.co/XxnkJrt/image.png

Подякували: P.Y., leofun01, mimik3

7

Re: iterator_category for references to pointer

Чому не задовольняє?
У чому полягає невідповідність?

Чим псевдодеструктор посилання на вказівник відрізняється від псевдодеструктора звичайного вказівника?
Це якось заважає посиланням бути ітераторами?

8 Востаннє редагувалося koala (18.09.2020 12:24:32)

Re: iterator_category for references to pointer

Посилання на ітератори не можуть бути ітераторами, бо ітераторами є те, на що вони посилаються.
Так само як і з арифметикою.

int a = 5;
int &ra = a;
ra++;//операція ++ застосовується не до ra, а до a
int arr[] = {1,2,3};
int *iter = arr;
int *&riter = iter;
riter++;//так само - ++ застосовується не до riter, а до iter

Ви не можете виконати з посиланням жодної операції, характерної для конкретно ітераторів - ви можете їх виконати лише з тим, на що вони посилаються, зокрема за допомогою цих посилань.

Подякували: leofun011

9

Re: iterator_category for references to pointer

wander написав:

Може скластися враження, що вказівник та ітератор тотожні речі, хоча це не так.

У деяких після фрази "кожен оселедець - риба" складається враження, що кожна риба - оселедець. Лікується, зазвичай, базовим курсом логіки.

Подякували: leofun011

10

Re: iterator_category for references to pointer

До речі, у вас dtor інстанціюється з типом int*, а не int*& :)

11

Re: iterator_category for references to pointer

Глобально нічого не змінює:

#include <type_traits>
#include <iostream>
 
template<class T> void dtor(T& v)
{
    v.~t();
}
 
int main()
{
    int* p;
    int*& r2 = p;
    dtor(r2);
}

12

Re: iterator_category for references to pointer

Naomi написав:

Глобально нічого не змінює:

Нічого окрім дечого :)

#include <type_traits>
#include <iostream>
 
template<class T> void dtor(T& v)
{
    boolalpha(std::cout);
    std::cout << std::is_reference_v<T> << '\n';
    v.~T();
}
 
int main()
{
    int* p;
    int*& r2 = p;
    dtor(r2);
}
false

13

Re: iterator_category for references to pointer

#include <type_traits>
#include <iostream>
 
template<class T> void dtor(T& v)
{
    boolalpha(std::cout);
    std::cout << std::is_reference_v<decltype(v)> << '\n';
    v.~T();
}
 
int main()
{
    int* p;
    int*& r2 = p;
    dtor(r2);
}
true

Шкода що ви не знаєте відповіді на просте запитання)

14 Востаннє редагувалося wander (18.09.2020 18:42:20)

Re: iterator_category for references to pointer

*FACEPALM*
А деструктор ви теж викликаєте decltype(v)?

#include <type_traits>
#include <iostream>
 
template<class T> void dtor(T& v)
{
    using reference_t = std::add_lvalue_reference_t<T>;
    boolalpha(std::cout);
    std::cout << std::is_same_v<T          , int*&> << '\n'; // false
    std::cout << std::is_same_v<reference_t, int*&> << '\n'; // true
    v.~reference_t(); // error
}
 
int main()
{
    int* p;
    int*& r2 = p;
    dtor(r2);
}
<source>: In instantiation of 'void dtor(T&) [with T = int*]':
<source>:17:12:   required from here
<source>:10:8: error: 'v' is not of type 'reference_t' {aka 'int*&'}
   10 |     v.~reference_t();
      |     ~~~^~~~~~~~~~~

Отож, бо і воно.

15

Re: iterator_category for references to pointer

Навіщо це потрібно?
Без цього ітератор ніяк не зможе ітеруватися?

16

Re: iterator_category for references to pointer

Змова в комітеті.

Подякували: leofun01, mimik2