Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
rikimaru2013
C++ Game Dev
2440 / 1133 / 240
Регистрация: 30.11.2013
Сообщений: 3,690
#1

Полная спецификация шаблона в перемешку с SFINAE - C++

02.01.2016, 18:49. Просмотров 440. Ответов 4
Метки нет (Все метки)

Добрый вечер,

код полностью не валидный, но показывает мои искренние старания. Желание написать C++11 generation template class, который бы отвечал следующим заявлиным требованиям:
C++
1
2
3
4
5
 cout << Random<int>::getFromTo( 3, 8 ) << endl;             // Expect int type - value(3..8)
    cout << Random<char>::getFromTo( 0, 255 ) << endl;          // Expect char type - value(0..255)
    cout << Random<bool>::getFromTo( false, true ) << endl;     // Expect bool type - value(false..true)
    cout << Random<float>::getFromTo( 1.3f, 4.4f ) << endl;     // Expect float type - value(1.3f..4.4f)
    cout << Random<Foo>::getFromTo( 2, 10 ) << endl;            // Expect Foo type - x value(2..10)
Задачу можно было бы решить сделав полную специализацию для классов явно указав бы типы
C++
1
2
3
4
5
6
template <typename T>
class Random;
template <>
class Random<float>;
template <>
class Random<double>;
Но это же не true coding - как смешать проверку SFINAE на факт нужно ли в exe данный класс и полную спецификацию, чтобы "научить" рендомить всё включая свои типы.

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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#include <iostream>
#include <random>
#include <chrono>
#include <type_traits>
#include <string>
using namespace std;
//////////////////////////////////////////////////////////////////////////
#ifndef OUT_TO_STREAM
 
#define OSTREAM_FRIEND(type_)  \
        template<class T> friend   \
        ::std::basic_ostream<T>&  \
        operator<<(::std::basic_ostream<T>& os, const type_& obj )
#endif
//////////////////////////////////////////////////////////////////////////
class Foo // for test
{
    int _x;
public:
    Foo(const Foo& copy)                        { _x = copy._x;}
    Foo(const int x) : _x(x)                    {}
    OSTREAM_FRIEND( Foo )
    {
        os << obj._x << endl;
        return os;
    }   
};
//////////////////////////////////////////////////////////////////////////
namespace RandomImplementation
{
 
    template <typename T, typename std::enable_if<std::is_integral<T>::value>::type* = nullptr>
    class RandomImpl
    {
    public:
        typedef T                               RType;
        typedef T                               InnerType;
        typedef long long                       MaxType;
 
        typedef std::uniform_int_distribution<MaxType>  uniform_dist;
        typedef std::default_random_engine      gen_type;
 
        gen_type                                m_generator;
 
 
        static RandomImpl*                      getInstance()
        {
            RandomImpl* singltone = new RandomImpl();
            return singltone;
        }
        RandomImpl() :
            m_generator( std::chrono::system_clock::now().time_since_epoch().count() )
        {
        }
 
        static MaxType getFromTo( const InnerType& from, const InnerType& to )
        {
            RandomImpl* instance = getInstance();
            uniform_dist uid_in_range( from, to );
            return uid_in_range( instance->m_generator );
        }
    };
    //----------------------------------------------------------------------------------------------------------------
    template <typename T, typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr>
    class RandomImpl
    {
    public:
        typedef T                               RType;
        typedef T                               InnerType;
        typedef long double                     MaxType;
 
        typedef std::uniform_real_distribution<MaxType>  uniform_dist;
        typedef std::default_random_engine      gen_type;
 
        gen_type                                m_generator;
 
 
        static RandomImpl*                      getInstance()
        {
            RandomImpl* singltone = new RandomImpl();
            return singltone;
        }
        RandomImpl() :
            m_generator( std::chrono::system_clock::now().time_since_epoch().count() )
        {
        }
 
        static MaxType getFromTo( const InnerType& from, const InnerType& to )
        {
            RandomImpl* instance = getInstance();
            uniform_dist uid_in_range( from, to );
            return uid_in_range( instance->m_generator );
        }
    };
}
//////////////////////////////////////////////////////////////////////////
 
//------------------------------------------------------------------------
template <typename T, typename std::enable_if<
    std::is_integral<T>::value &&
    !std::is_same<T, char>::value &&
    !std::is_same<T, bool>::value
                                            >::type* = nullptr>
class Random
{
public:
    typedef T                                   RType;
    typedef T                                   InnerType;
 
    static RType getFromTo( const InnerType& from, const InnerType& to )
    {
        return RandomImplementation::RandomImpl<T>::getFromTo( from, to );
    }
};
//------------------------------------------------------------------------
template <typename T, typename std::enable_if<std::is_same<T, char>::value>::type* = nullptr>
class Random
{
public:
    typedef char                                RType;
    typedef char                                InnerType;
 
    static RType getFromTo( const InnerType& from, const InnerType& to )
    {
        return RandomImplementation::RandomImpl<int>::getFromTo( from, to );
    }
};
//------------------------------------------------------------------------
template <typename T, typename std::enable_if<std::is_same<T, bool>::value>::type* = nullptr>
class Random
{
public:
    typedef bool                                RType;
    typedef bool                                InnerType;
 
    static RType getFromTo( const InnerType& from, const InnerType& to )
    {
        return RandomImplementation::RandomImpl<int>::getFromTo( from, to );
    }
};
template <typename T, typename std::enable_if<std::is_same<T, Foo>::value>::type* = nullptr>
class Random
{
public:
    typedef Foo                                RType;
    typedef int                                InnerType;
 
    static RType getFromTo( const InnerType& from, const InnerType& to )
    {
        int x = RandomImplementation::RandomImpl<int>::getFromTo( from, to );
        return Foo(x);
    }
};
 
//////////////////////////////////////////////////////////////////////////
int main()
{
    cout << Random<int>::getFromTo( 3, 8 ) << endl;             // Expect int type - value(3..8)
    cout << Random<char>::getFromTo( 0, 255 ) << endl;          // Expect char type - value(0..255)
    cout << Random<bool>::getFromTo( false, true ) << endl;     // Expect bool type - value(false..true)
    cout << Random<float>::getFromTo( 1.3f, 4.4f ) << endl;     // Expect float type - value(1.3f..4.4f)
    cout << Random<Foo>::getFromTo( 2, 10 ) << endl;            // Expect Foo type - x value(2..10)
}
0
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
02.01.2016, 18:49
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Полная спецификация шаблона в перемешку с SFINAE (C++):

SFINAE не работает - C++
Почему conversion operator не хочет работать ни так #include &lt;iostream&gt; #include &lt;type_traits&gt; class C { public: ...

Посоветуйте задания по SFINAE - C++
Добрый день, посоветуйте примеры заданий(само ТЗ задания, не код), которые вы бы решили/решали с помощью SFINAE. Последние задания...

Sfinae и иже с ним - C++
здравствуйте, дабы лучше разобраться с шаблонами решил сделать функцию, печатающую все элементы либо контейнера, либо массива. чтобы...

SFINAE придумайте задание - C++
Доброе утро, написал уже несколько реализаций с использованием технологии SFINAE. Придумайте мне задания еще на эту тему, чтобы лучше...

Выброс static_assert в failure SFINAE - C++
Добрый день, Пролог: куда я только static_assert не пихал))) Проблема: Ошибка error C2794: 'type': is not a member of any...

Ошибки intellisense Visual Studio при SFINAE - C++
Добрый вечер, что делать если intellisense Visual Studio не справляется с SFINAE и подчёркивает в любом случаи ?

4
hoggy
6717 / 2900 / 497
Регистрация: 15.11.2014
Сообщений: 6,523
Завершенные тесты: 1
02.01.2016, 19:58 #2
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
Но это же не true coding - как смешать проверку SFINAE на факт нужно ли в exe данный класс и полную спецификацию, чтобы "научить" рендомить всё включая свои типы.
не понятно, что именно не получается.
и зачем так много кода для такой простой задачи.

и зачем вообще нужны все эти шаблоны?
можно же было сделать тупо как то так:
C++
1
2
3
4
5
6
7
    uint32_t GetRandom(const uint32_t a, const uint32_t b);
    int32_t GetRandom(const int32_t a, const int32_t b);
    uint64_t GetRandom(const uint64_t a, const uint64_t b);
    int64_t GetRandom(const int64_t a, const int64_t b);
 
    f32_t GetRandom(const f32_t a, const f32_t b);
    f64_t GetRandom(const f64_t a, const f64_t b);
что бы вкрячить поддержку классов,
можно сделать что-то типа такого:

C++
1
2
3
4
5
6
7
8
9
10
11
template<class T> inline T random(const T& a, const T& b)
{
    static std::default_random_engine rnd_(
        static_cast<unsigned>(
            std::chrono::system_clock::now().time_since_epoch().count()
         )
    );
 
    std::uniform_int_distribution<T> distribution(a, b);
    return distribution(rnd_);
}
соответственно, все, что потребуется от возможных T:
отвечать контракту std::uniform_int_distribution
0
rikimaru2013
C++ Game Dev
2440 / 1133 / 240
Регистрация: 30.11.2013
Сообщений: 3,690
02.01.2016, 20:02  [ТС] #3
Цитата Сообщение от hoggy Посмотреть сообщение
все, что потребуется от возможных T:
отвечать контракту std::uniform_int_distribution
так код и писался, чтобы пофиксить это добавить возможность

Random<char> которую не подерживает uniform_int_distribution
и темболее Random<float> для которой надо uniform_real_distribution.

Ну вот горит желание предоставить функционал при это не "рассказывать" внутрености, что для float и Int разные поля, а для char вообще испобльзуйтеся int преобразованый в char.
1
hoggy
6717 / 2900 / 497
Регистрация: 15.11.2014
Сообщений: 6,523
Завершенные тесты: 1
02.01.2016, 20:41 #4
Лучший ответ Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от rikimaru2013 Посмотреть сообщение
так код и писался, чтобы пофиксить это добавить возможность
Random<char> которую не подерживает uniform_int_distribution
и темболее Random<float> для которой надо uniform_real_distribution.
Ну вот горит желание предоставить функционал при это не "рассказывать" внутрености, что для float и Int разные поля, а для char вообще испобльзуйтеся int преобразованый в char.

понял. за справочку мерси.
я и не знал про его ограничение
(на самом деле не задумывался,
потому что по факту ничто кроме интов не требовалось)

есть предожение: я вам сейчас каркас сооружу.
а вы его до ума доведите
(а то я внезапно даже и не в курсе про всякие там char и float.
а оно вон оно как, над пофиксить сэмпл)

Добавлено через 36 минут
http://rextester.com/DDB41931

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
122
123
124
#include <iostream>
 
#include <random>
#include <chrono>
 
#define dT \
    typename std::common_type<T1,T2>::type
 
namespace detailRandom{ 
 
    template<class T> struct property_
    {
        enum { eIS_BOOL = std::is_same<T, bool>::value }; 
        
        //TODO: как насчет wchar_t ???
        enum { eIS_CHAR 
            = std::is_same<T, char>::value 
           || std::is_same<T, unsigned char>::value 
           || std::is_same<T, signed char>::value 
        };
        
        enum { eIS_INTEGRAL = std::is_integral<T>::value && !eIS_CHAR && !eIS_BOOL };
        enum { eIS_FLOATING = std::is_floating_point<T>::value };
        enum { eIS_OTHER    = !eIS_CHAR && !eIS_INTEGRAL && !eIS_FLOATING };
    };
    
    template<class T>
    using for_integer 
        = typename std::enable_if< property_<T>::eIS_INTEGRAL >::type*;
    
    template<class T>
    using for_char 
        = typename std::enable_if< property_<T>::eIS_CHAR >::type*;
    
    template<class T>
    using for_bool
        = typename std::enable_if< property_<T>::eIS_BOOL >::type*;
    
    template<class T>
    using for_floating
        = typename std::enable_if< property_<T>::eIS_FLOATING >::type*;
    
    template<class T>
    using for_other
        = typename std::enable_if< property_<T>::eIS_OTHER >::type*;
    
 
    std::default_random_engine& rnd_()
    {
        static std::default_random_engine gen(
            static_cast<unsigned>(
                std::chrono::system_clock::now().time_since_epoch().count()
             )
        );
        return gen;
    }
    
    
 
} // namespace detailRandom
 
template<class T1, class T2, detailRandom::for_integer<dT> = nullptr> inline
dT random(const T1& a, const T2& b)
{
    std::uniform_int_distribution<dT> distribution(a, b);
    return distribution( detailRandom::rnd_());
}
 
template<class T1, class T2, detailRandom::for_floating<dT> = nullptr> inline
dT random(const T1& a, const T2& b)
{
    std::uniform_real_distribution<dT> distribution(a, b);
    return distribution( detailRandom::rnd_());
}
 
template<class T1, class T2, detailRandom::for_char<dT> = nullptr> inline
dT random(const T1& a, const T2& b)
{
    enum { eIS_SIGNED = std::is_signed<dT>::value };
    
    typedef typename std::conditional< eIS_SIGNED, int, unsigned >::type
        type;
    
    const auto a_ = static_cast<type>(a);
    const auto b_ = static_cast<type>(b);
    return static_cast<dT>(random( a_, b_));
}
 
 
template<class T1, class T2, detailRandom::for_bool<dT> = nullptr> inline
dT random(const T1& a, const T2& b)
{
    const auto a_ = static_cast<int>(a);
    const auto b_ = static_cast<int>(b);
    return static_cast<dT>(random( a_, b_));
}
#undef dT
 
 
int main()
{
    std::cout << "Hello, world!\n";
    
    std::cout << "integral: ";
    for(size_t n=0;n<10; ++n)
        std::cout << random(1,9)<<", ";
    std::cout << '\n';
    
    std::cout << "floating: ";
    for(size_t n=0;n<10; ++n)
        std::cout << random(1.0,9.0)<<", ";
    std::cout << '\n';
    
    std::cout << "char: ";
    for(size_t n=0;n<10; ++n)
        std::cout << random('a','g')<<", ";
    std::cout << '\n';
    
    std::cout << "bool: ";
    for(size_t n=0;n<10; ++n)
        std::cout << random(false, true)<<", ";
    std::cout << '\n';
    
}
5
zarko97
279 / 39 / 0
Регистрация: 11.10.2015
Сообщений: 405
05.02.2017, 18:23 #5
самопальный рандом, чары не поддерживает
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
/*******************************************************************************/
/*  RAND                                                                                                                */
/*****************************************************************************/
 
#ifndef RAND_H
#define RAND_H
 
#include       <random>
#include         <array>
#include   <type_traits>
#include    <algorithm>
#include      <typeinfo>
#include    <functional>
#include     <iostream>
 
namespace Mathematic
{
 
    template<class Dist = std::mt19937_64, std::uint64_t N = Dist::state_size>
    auto randomEngine() -> typename std::enable_if_t<N, Dist&>
    {
        std::array<typename Dist::result_type, N> seed_data;
        thread_local static std::random_device source;
        std::generate(std::begin(seed_data), std::end(seed_data), std::ref(source));
        std::seed_seq seeds(std::begin(seed_data), std::end(seed_data));
        thread_local static Dist seeded_engine(seeds);
        return seeded_engine;
    }
 
    template<class T>
    T random(const T& min, const T& max)
    {
        static_assert(std::is_arithmetic<T>::value, "an incompatible type.");
 
        using UniformInt = std::uniform_int_distribution<T>;
        using UniformReal = std::uniform_real_distribution<T>;
        using DistType = std::conditional_t<std::is_integral<T>::value, UniformInt, UniformReal>;
 
        static auto& RandomEngine = randomEngine();
 
        DistType uniformDistribution(min, max);
 
        return uniformDistribution(RandomEngine);
    }
}
#endif
0
05.02.2017, 18:23
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
05.02.2017, 18:23
Привет! Вот еще темы с ответами:

Обработка исключений. Спецификация - C++
Ниже описан код по обработке исключений. Вот какие появились вопросы: 1. Есть ли при обработке исключений автоматическое преобразование...

Спецификация файла. WTF? - C++
Здравствуйте. Что такое спецификация файла (в контексте данной задачи)? В Google ничего понятного не нашел. Заранее спасибо.

Определение метода-шаблона за пределами шаблона класса - C++
День добрый! Разбираюсь в шаблонах, решил копнуть поглубже. Вот пример: template &lt;typename T1&gt; class K // шаблон класса { public:...

Не полная адаптивность шаблона - HTML, CSS
Здравствуйте. Имеется довольно интересный шаблон Но дело в том, что он не совсем адаптивен. Вот как это выглядит. Кто...


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

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

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