42 / 42 / 17
Регистрация: 25.04.2014
Сообщений: 499

Детектировать итератор произвольного доступа

26.05.2016, 04:08. Показов 2343. Ответов 20
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
здравствуйте, нужно детектировать итератор произвольного доступа...
это не работает:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
template< typename... >
using void_t = void;
 
template< typename, typename = void_t<> >
struct has_random_access_iterator : std::false_type
{ };
 
template< typename Container >
struct has_random_access_iterator<Container, void_t<decltype(Container::iterator::operator-)>> : std::true_type
{ };
 
int main() {
    std::cout<<has_random_access_iterator<std::forward_list<abrakadabra>>::value<<"\n";     //выводит true
}
как сделать правильно?
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
26.05.2016, 04:08
Ответы с готовыми решениями:

Пишу итератор произвольного доступа
Пишу итератор произвольного доступа. По минимуму он должен поддерживать несколько операций, но меня смутила операция n+it, где n это целое...

Файл произвольного доступа
Здравствуйте, снова к файлам, такая задача. Допустим, у меня есть текстовый файл с данными - код, название, количество, и со значениями...

Файл произвольного доступа
Читаю Дейтелов, про файлы произвольного доступа. Написал вроде как по примеру, но что-то идет не так. Идея такая - создается файл, в нем...

20
19471 / 10080 / 2456
Регистрация: 30.01.2014
Сообщений: 17,763
26.05.2016, 09:33
Лучший ответ Сообщение было отмечено HighPredator как решение

Решение

tapochka,
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iterator>
#include <forward_list>
#include <vector>
#include <type_traits>
 
template <typename Iterator>
struct is_random_access_iterator
    : std::is_same<
        typename std::iterator_traits<Iterator>::iterator_category
      , std::random_access_iterator_tag
      >
{ };
 
template <typename Container>
struct has_random_access_iterator
    : is_random_access_iterator<typename Container::iterator>
{ };
 
int main() {
    std::cout<<has_random_access_iterator<std::forward_list<int>>::value<<"\n";     //выводит false
    std::cout<<has_random_access_iterator<std::vector<int>>::value<<"\n";     //выводит true
}
8
42 / 42 / 17
Регистрация: 25.04.2014
Сообщений: 499
26.05.2016, 22:47  [ТС]
DrOffset, благодарствую... а может еще и через void_t?)
0
19471 / 10080 / 2456
Регистрация: 30.01.2014
Сообщений: 17,763
27.05.2016, 00:04
Цитата Сообщение от tapochka Посмотреть сообщение
а может еще и через void_t?)
Не надо. Итератор может не быть классом, например typedef T * iterator;.
0
 Аватар для gromo
383 / 281 / 31
Регистрация: 04.09.2009
Сообщений: 1,225
27.05.2016, 01:16
Цитата Сообщение от DrOffset Посмотреть сообщение
Итератор может не быть классом
А что изменится в таком случае?
0
19471 / 10080 / 2456
Регистрация: 30.01.2014
Сообщений: 17,763
27.05.2016, 09:45
Цитата Сообщение от gromo Посмотреть сообщение
А что изменится в таком случае?
Ну если мы строим проверку на основе присутствия какого-то члена у класса, то понятно, что у встроенного типа ничего такого не будет. При этом мы знаем, что указатель является итератором. Т.е. получается, что если в какой-то из реализаций вектора итератор - это просто указатель (а такие были), то наш шаблон не сработает.

Дополнительно к этому, мы никак не защищены от ложного срабатывания. Т.е. то, что итератором не является, будет расцениваться нашим шаблоном как таковой - это тоже неправильно.
1
42 / 42 / 17
Регистрация: 25.04.2014
Сообщений: 499
28.05.2016, 19:06  [ТС]
DrOffset, почему если написать так, то ошибки:
opa.hpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
template<typename Container>
struct wrapper {
     template<typename Compare>
    typename std::enable_if<
            has_random_access_iterator<Container>::value,
            wrapper&
            >::type
        orderBy(Compare);
 
   template<typename Compare>
    typename std::enable_if<
            !has_random_access_iterator<Container>::value,
            wrapper&
            >::type
        orderBy(Compare); 
private:
    Container data;
}
 
template<typename Container>
template<typename Compare>
typename std::enable_if<has_random_access_iterator<Container>::value,
                        wrapper<Container>&
                        >::type
wrapper<Container>::orderBy(Compare func) {
    std::sort(std::begin(data),
              std::end(data),
              func);
    return *this;
}
 
template<typename Container>
template<typename Compare>
typename std::enable_if<!has_random_access_iterator<Container>::value,
                         wrapper<Container>&
                        >::type
wrapper<Container>::orderBy(Compare func) {
    data.sort(func);
    return *this;
}
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include "opa.hpp"
 
struct kop {
    std::string name;
    int age;
};
 
int main() {
{
    {
    std::vector<kop> ves = {{"gaafd", 43},{"fa",342},{"a",2},{"fdaf",0},{"fka a;f",0},{"fdf", 111},{"999",999}};
    wrapper<decltype(ves)> vesw(ves);
    vesw.
        orderBy([](kop el1, kop el2){
            return el1.age < el2.age;
        });
    }
    {
    std::list<kop> ves = {{"gaafd", 43},{"fa",342},{"a",2},{"fdaf",0},{"fka a;f",0},{"fdf", 111},{"999",999}};
        wrapper<decltype(ves)> vesw(ves);
        vesw.
        orderBy([](kop el1, kop el2){
            return el1.age < el2.age;
        });
    }
}
а если так(тупо функции без класса):
opa1.hpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
template<typename Container, typename Compare>
typename std::enable_if<has_random_access_iterator<Container>::value,
                        Container&
                        >::type
orderBy(Container& data, Compare func) {
    std::sort(std::begin(data),
              std::end(data),
              func);
    return data;
}
 
template<typename Container, typename Compare>
typename std::enable_if<has_random_access_iterator<Container>::value,
                         Container&
                        >::type
    orderBy(Container& data, Compare func) {
    data.sort(func);
    return data;
}
C++
1
2
3
4
5
6
7
8
9
10
11
#include "opa1.hpp"
int main() {
    std::vector<kop> vess = {{"gaafd", 43},{"fa",342},{"a",2},{"fdaf",0},{"fka a;f",0},{"fdf", 111},{"999",999}};
        orderBy(vess,[](kop el1, kop el2){
            return el1.age < el2.age;
        });
        std::list<kop> vesl = {{"gaafd", 43},{"fa",342},{"a",2},{"fdaf",0},{"fka a;f",0},{"fdf", 111},{"999",999}};
        orderBy(vesl,[](kop el1, kop el2){
            return el1.age < el2.age;
        });
}
то ошибок нет... сфинае то одинаковое по сути...
0
 Аватар для zarko97
279 / 39 / 13
Регистрация: 11.10.2015
Сообщений: 405
05.01.2017, 17:30
Лучше вообще абстрагироваться от std::, ибо во многих кастомных итераторах вообще не специализируется std::iterator_traits

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <type_traits>
#include <iterator>
 
namespace detail {
 
    template<class ...>
    struct param_tester
    {
        using type = void;
    };
 
    template<class... Args>
    using void_t = typename param_tester<Args...>::type;
 
    template<class It, class void_t = void>
    struct is_iterator : std::false_type {};
 
    template<class It>
    struct is_iterator<It,
        void_t< 
        decltype(++std::declval<It&>()),
        decltype(--std::declval<It&>()),
        decltype(*std::declval<It&>()),
        decltype(std::declval<It&>() + std::declval<std::ptrdiff_t>()),
        decltype(std::declval<It&>() - std::declval<std::ptrdiff_t>()),
        decltype(std::ptrdiff_t(std::declval<It&>() - std::declval<const It&>())),
        decltype(std::declval<It&>() += std::declval<std::ptrdiff_t>()),
        decltype(std::declval<It&>() -= std::declval<std::ptrdiff_t>()),
        decltype(std::declval<It&>() == std::declval<const It&>()),
        decltype(std::declval<It&>() = std::declval<const It&>())
        >
    > : std::true_type {};
 
    template<class It>
    struct is_iterator<It*,
        typename std::enable_if_t<std::is_pointer<It>::value>>  : std::true_type {};
 
    template<class It>
    struct is_iterator<const It*, 
        typename std::enable_if_t<std::is_pointer<It>::value>> : std::true_type {};
 
    template<class It>
    using is_iterator_t = typename is_iterator<It>::type;
}
Добавлено через 3 минуты
А чо будем делать, если мы юзаем итератор без std::iterator_traits? ))
2
42 / 42 / 17
Регистрация: 25.04.2014
Сообщений: 499
05.01.2017, 22:46  [ТС]
Цитата Сообщение от zarko97 Посмотреть сообщение
Лучше вообще абстрагироваться от std::
холиварный вопрос: а почему это лучше?
0
 Аватар для zarko97
279 / 39 / 13
Регистрация: 11.10.2015
Сообщений: 405
06.01.2017, 00:40
По-моему я уже ответил на этот вопрос ))
Под свои нужды можно конечно и итератор_траитс юзать, но если ваш код будет использоваться вне зависимостей от стд то могут возникнуть проблемки

Добавлено через 1 минуту
я напутал немного с реализацией...правильнее будет как-то так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
template<class ...>
    struct param_tester
    {
        using type = void;
    };
 
    template<class... Args>
    using void_t = typename param_tester<Args...>::type;
 
    template<class It, class voider = void_t<>>
    struct is_iterator : std::false_type {};
 
    template<class It>
    struct is_iterator<It,
        void_t< 
        decltype(++std::declval<It&>()),
        decltype(--std::declval<It&>()),
        decltype(*std::declval<It&>()),
        decltype(std::declval<It&>() + std::declval<std::ptrdiff_t>()),
        decltype(std::declval<It&>() - std::declval<std::ptrdiff_t>()),
        decltype(std::ptrdiff_t(std::declval<It&>() - std::declval<const It&>())),
        decltype(std::declval<It&>() += std::declval<std::ptrdiff_t>()),
        decltype(std::declval<It&>() -= std::declval<std::ptrdiff_t>()),
        decltype(std::declval<It&>() == std::declval<const It&>()),
        decltype(std::declval<It&>() = std::declval<const It&>())
        >
    > : std::true_type {};
 
    template<class It>
    using is_iterator_t = typename is_iterator<It>::type;
0
42 / 42 / 17
Регистрация: 25.04.2014
Сообщений: 499
06.01.2017, 01:20  [ТС]
zarko97, ну если вам каждый такт важен, то может std:: и не нужно...

из стандарта:
A type X satisfies the Iterator requirements if:
— X satisfies the CopyConstructible, CopyAssignable, and Destructible requirements (17.6.3.1) and
lvalues of type X are swappable (17.6.3.2), and
— the expressions in Table 106 are valid and have the indicated semantics.
если я правильно понял, ваш детектор итератора не проверяет на CopyAssignable and Destructible и swappable
0
 Аватар для zarko97
279 / 39 / 13
Регистрация: 11.10.2015
Сообщений: 405
06.01.2017, 11:28
это самая тривиальная реализация
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
06.01.2017, 17:08
Цитата Сообщение от zarko97 Посмотреть сообщение
Лучше вообще абстрагироваться от std::, ибо во многих кастомных итераторах вообще не специализируется std::iterator_traits
не совместимое с std идет лесом.
1
 Аватар для zarko97
279 / 39 / 13
Регистрация: 11.10.2015
Сообщений: 405
14.01.2017, 16:03
tapochka, ну с проверками так (swappable не охота клипать):
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#ifndef TTR_H
#define TTR_H
 
#include <functional>
#include <type_traits>
#include <iterator>
 
namespace detail {
 
    template<class ...>
    struct param_tester
    {
        using type = void;
    };
 
    template<class... Args>
    using void_t = typename param_tester<Args...>::type;
 
    template<class Iter>
    struct has_iterator
    {
        static constexpr bool value_t = std::is_copy_constructible<Iter>::value &&
                                        std::is_copy_assignable<Iter>::value && 
                                        std::is_destructible<Iter>::value;
    };
 
    template<class It, class voider = void_t<>>
    struct is_iterator : std::false_type {};
 
    template<class It>
    struct is_iterator<It,
        void_t
        <
        decltype(++std::declval<It&>()),
        decltype(--std::declval<It&>()),
        decltype(*std::declval<It&>()),
        decltype(std::ptrdiff_t(std::declval<It&>().operator[](std::declval<std::ptrdiff_t>()))),
        decltype(std::declval<It&>() + std::declval<std::ptrdiff_t>()),
        decltype(std::declval<It&>() - std::declval<std::ptrdiff_t>()),
        decltype(std::ptrdiff_t(std::declval<It&>() - std::declval<const It&>())),
        decltype(std::declval<It&>() += std::declval<std::ptrdiff_t>()),
        decltype(std::declval<It&>() -= std::declval<std::ptrdiff_t>()),
        decltype(std::declval<It&>() == std::declval<const It&>()),
        decltype(std::declval<It&>() = std::declval<const It&>())
        >
    > : std::integral_constant<bool, has_iterator<It>::value_t || std::is_pointer<It>::value> {};
    
    template<class It>
    using is_iterator_t = typename is_iterator<It>::type;
 
}
#endif
1
 Аватар для zarko97
279 / 39 / 13
Регистрация: 11.10.2015
Сообщений: 405
30.01.2017, 01:15
tapochka, вот такой отстой получился...чего-то не идет у меня, вчера только последний экзамен сдал
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
struct wrap {};
 
template<class T>  
struct is_swappable
{
    using yes_type = char;
    using no_type = struct { char array[2]; };
    template<class X> static decltype(*static_cast<X*>(0).std::swap(*static_cast<X*>(0)))* type_if(X*);
    static constexpr wrap type_if(...);
    template<class X> static constexpr yes_type helper(X*);
    static constexpr no_type helper(wrap);
    static constexpr bool value = sizeof(helper(type_if((T*)0))) == sizeof(yes_type);
};
1
 Аватар для zarko97
279 / 39 / 13
Регистрация: 11.10.2015
Сообщений: 405
05.02.2017, 12:36
tapochka, чего-то я напылил тут...можно проще :
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
namespace dispatch {
 
    using std::swap;
 
    template<class T, class voider = void_t<>>
    struct has_member_swap : std::false_type { };
 
    template<class T>
    struct has_member_swap<T,
         void_t<decltype(std::declval<T&>().swap(std::declval<T&>()))>
         > : std::integral_constant<bool, 
          std::is_move_assignable<T>::value && 
          std::is_move_constructible<T>::value
    > { };
    }
0
 Аватар для zarko97
279 / 39 / 13
Регистрация: 11.10.2015
Сообщений: 405
23.02.2017, 15:32
hoggy, Кто идет? Многие проекты пишутся без таких зависимостей от std — соответственно, в них никто специализировать std::iterator_traits для кастомных итераторов не будет. Это общеизвестный факт...
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
23.02.2017, 16:42
Цитата Сообщение от zarko97 Посмотреть сообщение
Многие проекты пишутся без таких зависимостей от std
1.
ни один серьёзный не пишется без зависимостей от std.

2.
древние проекты велосипедили инструменталку по причине того,
что в древние времена стандарт был не устоявшимся.
поэтому, фреймворки вынуждены были поддерживать собственные стандарты.
в нынешние времена велосипеды приводят в соответствие стандарту с++.
так например QT вполне себе совместим с std.

3.
механика, которую нельзя эксплуатировать совместо
со всякие алгоритмами std - ущербна.
нет никаких причин ограничивать область применения
инструментальных механизмов.

4.
велосипедить в нынешние времена что-то,
оторванное от плюсовой экосистемы -
это какое то велосипедирование ради велосипедирования.
дилетанские поделия.


Цитата Сообщение от zarko97 Посмотреть сообщение
никто специализировать std::iterator_traits для кастомных итераторов не будет.
5.
если ваш кастомный итератор нельзя использовать в алгоритмах std
наравне с прочими грамотно выполнеными итераторами,
тогда грош цена вашу итератору.
на бою используют профессионально выполненные инструменты,
а не игрушки.

Цитата Сообщение от zarko97 Посмотреть сообщение
Это общеизвестный факт
не нужно выдавать субъективное за объективное.
или назовите хотя бы один коммерческий проект,
который не использовал бы стандартую библиотеку.
1
 Аватар для zarko97
279 / 39 / 13
Регистрация: 11.10.2015
Сообщений: 405
26.02.2017, 16:52
tapochka, вот финальная реализация...я конечно задрал вас уже
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
namespace dispatch {
 
        using std::swap;
 
        template<class T, class voider = void_t<> >
        struct is_swapable : std::false_type { };
 
        template<class T>
        struct is_swapable<T,
            void_t<decltype(swap(std::declval<T&>(), std::declval<T&>())), typename std::enable_if_t<!std::is_array<T>::value> >
        > : std::integral_constant<bool,
            std::is_move_assignable<T>::value &&
            std::is_move_constructible<T>::value
        > { };
 
        template<class T>
        struct is_swapable<T, typename std::enable_if_t<std::is_array<T>::value> > : is_swapable<std::remove_all_extents_t<T> > { };
    }
0
26.02.2017, 21:46  [ТС]

Не по теме:

zarko97, ну все, можно на этом успокоиться)

0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
26.02.2017, 21:46
Помогаю со студенческими работами здесь

Файл произвольного доступа
Очень прошу помощи так как не могу с ними разобраться который день, видать делаю одну и ту же ошибку но не нахожу. Создаю свой класс и...

Deque - сложность произвольного доступа
Тут написано: как так? Я привык считать, что дек - хранится двусвязным списком....

Создание файла произвольного доступа
Здравствуйте.Ни как не могу разобраться с файлами произвольного доступа.Но эта тема посвящена именно созданию таких файлов. #include...

Создание файла произвольного доступа.
#include &lt;iostream.h&gt; #include &lt;fstream.h&gt; #include &lt;stdlib.h&gt; #define number 100 struct clientData { int acctNum; ...

Обработка файлов произвольного доступа
Создать файл, содержащий массив указателей на упорядоченные в алфавитном порядке строки, представленные записями переменной длины....


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

Новые блоги и статьи
Деплой Flask приложения
py-thonny 23.06.2025
За годы работы с Flask я натыкался на одни и те же грабли достаточно часто, чтобы наконец научится их обходить. И сегодня хочу поделится опытом, который сбережет вам немало нервных клеток. Начнем с. . .
WebAssembly и контейнеры в .NET Aspire для оркестрации распределенных архитектур
ArchitectMsa 23.06.2025
Я наблюдаю, как WebAssembly (или просто WASM) постепенно выходит за рамки своего первоначального предназначения — исполнения кода на стороне браузера. Теперь эта технология проникает в серверную. . .
Непрерывная интеграция для пакета Python
Mr. Docker 22.06.2025
Было 4 часа утра пятницы, когда я выпустил новую версию нашей внутренней библиотеки для обработки данных. Релиз 0. 5. 2 содержал небольшой фикс для обработки дат в ISO формате, что может пойти не так?. . .
Продвинутый ETL на C# из OLTP БД в хранилище
stackOverflow 22.06.2025
Работая в сфере корпоративной аналитики, я постоянно сталкиваюсь с одним и тем же - нужны чистые, структурированные и, главное, свежие данные. Без них современные аналитические системы, машинное. . .
Мастер-класс по микросервисам на Node.js
Reangularity 21.06.2025
Node. js стал одной из самых популярных платформ для микросервисной архитектуры не случайно. Его неблокирующая однопоточная модель и событийно-ориентированный подход делают его идеальным для. . .
Управление Arduino из WPF приложения
Wired 21.06.2025
Зачем вообще связывать Arduino с WPF-приложением? Казалось бы, у Arduino есть собственная среда разработки, своя экосистема, свои способы управления. Однако при создании серьезных проектов. . .
Звёздная пыль
kumehtar 20.06.2025
Я просто это себе представляю: как создавался этот мир. Как энергия слипалась в маленькие частички. Как они собирались в первые звёзды, как во вселенной впервые появился Свет. Как эти звёзды. . .
Создание нейросети с PyTorch
AI_Generated 19.06.2025
Ключевое преимущество PyTorch — его питоновская натура. В отличие от TensorFlow, который изначально был построен как статический вычислительный граф, PyTorch предлагает динамический подход. Это. . .
JWT аутентификация в ASP.NET Core
UnmanagedCoder 18.06.2025
Разрабатывая веб-приложения, я постоянно сталкиваюсь с дилеммой: как обеспечить надежную аутентификацию пользователей без ущерба для производительности и масштабируемости? Классические подходы на. . .
Краткий курс по С#
aaLeXAA 18.06.2025
Здесь вы найдете все необходимые функции чтоб написать програму на C# Задание 1: КЛАСС FORM 1 public partial class Form1 : Form { Spisok listin = new Spisok(); . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru