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

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

Войти
Регистрация
Восстановить пароль
Другие темы раздела
C++ Не выводятся на экран значения элементов массива http://www.cyberforum.ru/cpp-beginners/thread1630346.html
const int arraySize = 10; int data = { 34, 56, 4, 10, 77, 51, 93, 30, 5, 52 }; cout << "Unsorted array:\n"; for(int i = 0; i < arraySize; ++i) cout << setw(4) << data;...
C++ Вычислить сумму ряда целых чисел кратных 3 которая меньше 21 Вычислить сумму ряда целых чисел кратных 3, которая меньше 21. Вывести результат, последний член и количество итераций http://www.cyberforum.ru/cpp-beginners/thread1630332.html
Проверить принадлежит ли введенное число заданному диапазону C++
Введіть з клавіатури два числадля більшого з них числа перевірте чи знаходиться воно вдіапазоні від 5до30 Ввести 2 числа. Для большего из них проверить принадлежит ли оно диапазону от 5 до 30....
Получение времени в С++, time.h C++
Всем доброго времени суток. Сталкиваюсь с проблемой получения времени. Под запись в БД мне необходимо получить именно СЕКУНДЫ, а не дату, и записать их в строку. Получать необходимо много раз,...
C++ Проверить введённое пользователем число на соответствие условию http://www.cyberforum.ru/cpp-beginners/thread1630311.html
Напишите программу, которая позволяет вводить данные, использует вложенный условный оператор, и выводит на экран 4 соответствующих сообщения. Введите с клавиатуры целое число N. Если оно парное ,...
C++ Найти и исправить ошибки в коде (массивы) y=0; for(i=1;i<=F;i++) { y=y+w*x; cout<<y; } Выдает нули для всех y. Помогите новичку пожалуйста. подробнее

Показать сообщение отдельно
rikimaru2013
C++ Game Dev
2436 / 1130 / 240
Регистрация: 30.11.2013
Сообщений: 3,687

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

02.01.2016, 18:49. Просмотров 385. Ответов 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
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru