Форум программистов, компьютерный форум CyberForum.ru

C++

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 1, средняя оценка - 5.00
Croessmah
Модератор
Эксперт CЭксперт С++
13052 / 7315 / 814
Регистрация: 27.09.2012
Сообщений: 18,052
Записей в блоге: 3
Завершенные тесты: 1
#1

Применение is_same для списка типов - C++

01.02.2016, 03:16. Просмотров 665. Ответов 17
Метки нет (Все метки)

Итак, std::is_same может сравнить только два типа.
Написал велосипед,
который сравнивает первый тип со всеми остальными.
Собственно, вот код:
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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#include <type_traits>
 
 
// =========================================================================================================
// ================================================is_same_list=============================================
// =========================================================================================================
 
 
namespace detail
{
 
 
 
struct is_same_list_impl
{
    template<
        template<bool,bool> class LogicTemplate,
        typename SameType,
        typename FirstType,
        typename ... Args
    >
    static
    constexpr std::enable_if_t<sizeof...(Args)!=0,bool>
    constexpr_call()
    {
        return
                LogicTemplate<
                    std::is_same<
                        SameType,
                        FirstType
                    >::value,
                    constexpr_call<LogicTemplate, SameType, Args...>()
                >::value ;
    }
 
 
 
    template<
        template<bool,bool> class LogicTemplate,
        typename SameType,
        typename FirstType,
        typename ... Args
    >
    static
    constexpr std::enable_if_t<sizeof...(Args)==0,bool>
    constexpr_call()
    {
        return
                std::is_same<
                    SameType,
                    FirstType
                >::value ;
    }
};
 
 
 
 
 
}//end of detail
 
 
 
 
namespace compile_time
{
    template<bool First, bool Second>
    struct constexpr_logical_and
    {
        static constexpr bool value = First && Second ;
    };
 
 
    template<bool First, bool Second>
    struct constexpr_logical_or
    {
        static constexpr bool value = First || Second ;
    };
}//end of compile_time
 
 
 
template<typename First, typename Second>
struct is_same_decay
{
    static constexpr bool value =
            std::is_same<
                std::decay_t<First>,
                std::decay_t<Second>
            >::value ;
};
 
 
template<typename SameType, typename ... Args>
struct is_all_same
{
    static constexpr bool value =
            detail::is_same_list_impl::constexpr_call<
                compile_time::constexpr_logical_and,
                SameType, Args...
            >() ;
};
 
 
template<typename SameType, typename ... Args>
struct is_one_same
{
    static constexpr bool value =
            detail::is_same_list_impl::constexpr_call<
                compile_time::constexpr_logical_or,
                SameType, Args...
            >() ;
};
 
 
 
 
 
// =========================================================================================================
// =========================================================================================================
// =========================================================================================================
is_one_same - определяет, есть ли в списке параметров хоть один тип, одинаковый с первым в списке,
т.е. false, если все типы отличны от первого, true - во всех остальных случаях.
is_all_same - определяет, все ли типы в списке одинаковые,
т.е. true, если все типы соответствуют первому, false - во всех остальных случаях.



Пример использования:
C++
1
2
3
4
5
6
7
8
9
10
int main(int argc, char ** argv)
{
    std::cout << is_all_same<int,int,float,double,int&>::value << std::endl ; //false
    std::cout << is_all_same<int,int,int,int,int&>::value << std::endl ;//false 
    std::cout << is_all_same<int,int,int,int,int>::value << std::endl ;//true
    std::cout << std::endl ;
    std::cout << is_one_same<int,int,float,double,int&>::value << std::endl ;//true
    std::cout << is_one_same<int,std::ostream,float,double,unsigned int>::value << std::endl ;//false
    std::cout << is_one_same<int,int,int,int,int>::value << std::endl ;//true
}
http://rextester.com/CZFY1496

Для чего это мне может пригодится, опишу в теме Обертка над boost::lexical_cast для работы с unsigned типами
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
01.02.2016, 03:16     Применение is_same для списка типов
Посмотрите здесь:
C++ Используя производные классы, определить класс параметризованного списка одного из следующих типов. Применить его для построения списка объектов указа
Применение в программах однозвсвязного списка C++
C++ Найти предельные значения для целочисленных типов. Не использовать заранее определенные константы границ типов.
C++ Применение strtok() для получения слова
C++ Проблемы с приведением типов для компоранда для qsort
C++ Применение циклов для расчета параметров объектов на С++
Применение симплекс-метода для решения задач C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
ForEveR
В астрале
Эксперт С++
7970 / 4732 / 320
Регистрация: 24.06.2010
Сообщений: 10,541
Завершенные тесты: 3
01.02.2016, 10:35     Применение is_same для списка типов #2
Croessmah, В С++14 можно юзать std::logical_and/std::logical_or они constexpr cудя по документации.
Есть подозрение что можно реализовать is_same проще.
Croessmah
Модератор
Эксперт CЭксперт С++
13052 / 7315 / 814
Регистрация: 27.09.2012
Сообщений: 18,052
Записей в блоге: 3
Завершенные тесты: 1
01.02.2016, 10:38  [ТС]     Применение is_same для списка типов #3
Цитата Сообщение от ForEveR Посмотреть сообщение
В С++14 можно юзать std::logical_and/std::logical_or они constexpr cудя по документации.
Да, в 14-ом стандарте оно constexpr.
Но на случай, если переделать нужно будет на 11-ый, пусть висит.
Kastaneda
Форумчанин
Эксперт С++
4511 / 2853 / 227
Регистрация: 12.12.2009
Сообщений: 7,249
Записей в блоге: 1
Завершенные тесты: 1
01.02.2016, 11:12     Применение is_same для списка типов #4
Цитата Сообщение от ForEveR Посмотреть сообщение
Есть подозрение что можно реализовать is_same проще.
Поддерживаю.
Глядя на код, складывается впечатление, что хотелось применить как можно больше всяких фич (так бывает после прочтения новой книги), из-за чего код получился неоправданно сложный.

Не по теме:

После того, как я научился применять SFINAE-фичи из С++11 я написал в рабочем проекте класс, в котором один и тот же метод реализован для разных типов при помощи enable_if, тогда мне показалось это круто. Уже позже глядя на это я понял, что это решается банальной перегрузкой, которая описана в начале любой книги по С++ для начинающих. Не надо доводить себя до такого, это плохо Если есть простое простое решение - нужно использовать простое решение.

Croessmah
Модератор
Эксперт CЭксперт С++
13052 / 7315 / 814
Регистрация: 27.09.2012
Сообщений: 18,052
Записей в блоге: 3
Завершенные тесты: 1
01.02.2016, 12:35  [ТС]     Применение is_same для списка типов #5
Цитата Сообщение от Kastaneda Посмотреть сообщение
Поддерживаю.
Как раз занимаюсь

Добавлено через 27 минут
Переделал так:
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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
// =========================================================================================================
// ================================================is_same_list=============================================
// =========================================================================================================
 
 
#include <type_traits>
 
namespace detail
{
 
    template<
        template<class T> class LogicTemplate,
        typename SameType
    >
 
    constexpr bool
    is_same_list_impl()
    {
        return !LogicTemplate<bool>()(true,false) ;
    }
 
 
    template<
    template<class T> class LogicTemplate,
        typename SameType,
        typename FirstType,
        typename ... Args
    >
    constexpr bool
    is_same_list_impl()
    {
        return
                LogicTemplate<bool>()(std::is_same<SameType, FirstType>::value,
                    is_same_list_impl<LogicTemplate, SameType, Args...>()
                ) ;
    }
 
 
 
}//end of detail
 
 
 
 
namespace compile_time
{
    template<class T>
    struct logical_and : public std::binary_function<T,T,bool>
    {
        constexpr bool operator()(const T& first, const T& second) { return first && second ; }
    };
 
 
    template<class T>
    struct logical_or : public std::binary_function<T,T,bool>
    {
        constexpr bool operator()(const T& first, const T& second) { return first || second ; }
    };
}//end of compile_time
 
 
 
 
template<typename SameType, typename ... Args>
struct is_all_same
{
    static constexpr bool value =
            detail::is_same_list_impl<
                compile_time::logical_and,
                SameType, Args...
            >() ;
};
 
 
template<typename SameType, typename ... Args>
struct is_one_same
{
    static constexpr bool value =
            detail::is_same_list_impl<
                compile_time::logical_or,
                SameType, Args...
            >() ;
};
 
 
 
 
 
// =========================================================================================================
// =========================================================================================================
// =========================================================================================================
Почему-то ночью так не получалось,
видать спал больше

Добавлено через 8 минут
Цитата Сообщение от ForEveR Посмотреть сообщение
В С++14 можно юзать std::logical_and/std::logical_or они constexpr cудя по документации.
Оставил свое, только переделал под один интерфейс.
В gcc 4.9.3 с ключем -std=c++14
всё равно std::logical_and/std::logical_or без constexpr
Печалька.
ct0r
Игогошка!
1768 / 670 / 42
Регистрация: 19.08.2012
Сообщений: 1,284
Завершенные тесты: 1
01.02.2016, 14:09     Применение is_same для списка типов #6
Croessmah, я мельком глянул, наверное что-то упустил, но почему так не катит?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
template <class ...T> struct is_all_same;
 
template <class T>
struct is_all_same<T> {
    static constexpr bool value = true;
};
 
template <class T, class U, class... V>
struct is_all_same<T, U, V...> {
    static constexpr bool value = std::is_same<T, U>() && is_all_same<U, V...>::value;
};
 
template <class ...T> struct is_one_same;
 
template <class T>
struct is_one_same<T> {
    static constexpr bool value = false;
};
 
template <class T, class U, class... V>
struct is_one_same<T, U, V...> {
    static constexpr bool value = std::is_same<T, U>() || is_one_same<T, V...>::value;
};
Croessmah
Модератор
Эксперт CЭксперт С++
13052 / 7315 / 814
Регистрация: 27.09.2012
Сообщений: 18,052
Записей в блоге: 3
Завершенные тесты: 1
01.02.2016, 14:23  [ТС]     Применение is_same для списка типов #7
Цитата Сообщение от ct0r Посмотреть сообщение
наверное что-то упустил, но почему так не катит?
Да я ночью что только не перепробовал - не канает.
Но это я что-то упустил, а не Вы.

Добавлено через 3 минуты

Не по теме:

Цитата Сообщение от Kastaneda Посмотреть сообщение
SFINAE-фичи из С++11 я написал в рабочем проекте класс
я учусь, мне можно

Croessmah
Модератор
Эксперт CЭксперт С++
13052 / 7315 / 814
Регистрация: 27.09.2012
Сообщений: 18,052
Записей в блоге: 3
Завершенные тесты: 1
01.02.2016, 14:39  [ТС]     Применение is_same для списка типов #8
Цитата Сообщение от Kastaneda Посмотреть сообщение
нужно
В конце же останется
C++
1
is_all_same<U, пусто>::value;
Но, думаю, и так и так сработает.
Kastaneda
Форумчанин
Эксперт С++
4511 / 2853 / 227
Регистрация: 12.12.2009
Сообщений: 7,249
Записей в блоге: 1
Завершенные тесты: 1
01.02.2016, 14:50     Применение is_same для списка типов #9
Цитата Сообщение от Croessmah Посмотреть сообщение
В конце же останется
не, не осталось бы, просто этот вариант раньше бы вызвался, чем вариант с одним <T>. Но вариант с одним <T> тоже рабочий, я просто прогнал.

Добавлено через 13 секунд
Цитата Сообщение от Croessmah Посмотреть сообщение
и так и так сработает.
ага

Не по теме:

Цитата Сообщение от Croessmah Посмотреть сообщение
я учусь, мне можно
Я тоже учусь, только прямо в рабочем проекте, и поскольку я тут ведущий инженер, мне тоже можно

Croessmah
Модератор
Эксперт CЭксперт С++
13052 / 7315 / 814
Регистрация: 27.09.2012
Сообщений: 18,052
Записей в блоге: 3
Завершенные тесты: 1
01.02.2016, 15:20  [ТС]     Применение is_same для списка типов #10

Не по теме:

Цитата Сообщение от Kastaneda Посмотреть сообщение
Я тоже учусь, только прямо в рабочем проекте, и поскольку я тут ведущий инженер, мне тоже можно
И меня научи



Добавлено через 9 минут
Во, понял что я упустил.
C++
1
2
3
4
template <class T, class U, class... V>
struct is_all_same {//забыл <T, U, V...>
    static constexpr bool value = std::is_same<T, U>() && is_all_same<U, V...>::value;
};
во всяком случае, список ошибок тот же
DrOffset
7058 / 4199 / 949
Регистрация: 30.01.2014
Сообщений: 6,965
02.02.2016, 13:07     Применение is_same для списка типов #11
ct0r, Croessmah, Можно проще и без рекурсии:
C++
1
2
3
4
5
6
7
template <typename ...T>
struct pack {};
 
template <typename T, typename... V>
struct is_all_same
    : std::is_same< pack<T, V...>, pack<V..., T> >
{ };
Kastaneda
Форумчанин
Эксперт С++
4511 / 2853 / 227
Регистрация: 12.12.2009
Сообщений: 7,249
Записей в блоге: 1
Завершенные тесты: 1
02.02.2016, 13:17     Применение is_same для списка типов #12
DrOffset, не сразу понял, круто!
ct0r
Игогошка!
1768 / 670 / 42
Регистрация: 19.08.2012
Сообщений: 1,284
Завершенные тесты: 1
02.02.2016, 13:30     Применение is_same для списка типов #13
DrOffset, я бы так скорее всего не писал, но прием забавный однако
DrOffset
02.02.2016, 13:59
  #14

Не по теме:

Цитата Сообщение от ct0r Посмотреть сообщение
я бы так скорее всего не писал
Почему?

MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
02.02.2016, 14:13     Применение is_same для списка типов
Еще ссылки по теме:
C++ Применение Map для парсинга строк с числами
Почему при выводе указателя получаем для char - значение по адресу, а для других типов - адрес C++
Реализовать двусвязный список. В разных узлах одного списка может быть любой объект одного из допустимых типов (своих знаний не хватает) C++
Используя перегрузки, написать функцию для выполнения действий, для следующих типов данных: float, int, double C++
Применение симплекс-метода для решения экономических задач C++

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

Или воспользуйтесь поиском по форуму:
ct0r
02.02.2016, 14:13     Применение is_same для списка типов
  #15

Не по теме:

Цитата Сообщение от DrOffset Посмотреть сообщение
Почему?
Потому что при чтении недостаточно просто бросить взгляд на код, чтобы понять, как оно работает и почему. Вон даже Kastaneda сразу не понял Ну и хочется одинаковой структуры с is_one_same.

Yandex
Объявления
02.02.2016, 14:13     Применение is_same для списка типов
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru