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

Специализация метода темплейтного класса вложенного в темплейтный класс - C++

Восстановить пароль Регистрация
Другие темы раздела
OpenGL OpenGL, трехмерный график http://www.cyberforum.ru/cpp-beginners/thread1497375.html
Начинаю по чуть-чуть изучать программирование , попалась для меня немного странная задачка , нужно вывести график функции z=cos(r)/r , но при этом r=sqrt((x^2)*(y^2)). выдает много ошибок , прошу помощи в их исправление или советов. #include<openGL/gl.h> #include<Glut/glut.h> #include <math.h> #include <stdlib.h> float f(float x, float y , float r , float z) { return...
C++ Крестики-нолики - алгоритм для игры против ПК Смотрю, уже только ленивый не сделал. Собственно это я. Вчера сел, написал свои 200 строк какашкокода для любого поля с любым количеством требуемых чисел для победы по всем направлениям.. С победой пришлось повозиться, но все вышло. Собственно, куда смотреть в отношении алгоритма для игры против ПК? Очевидно, что рандом так себе играет. Пока есть следующий вариант: if Проверить возможность... http://www.cyberforum.ru/cpp-beginners/thread1497338.html
Запись двумерного массива в файл C++
В общем нужно записать двумерный массив в фаил, но что то ни как не получается. //magicQuad.h #ifndef MAGICQUAD_H #define MAGICQUAD_H #include <iostream> using std::cout; using std::endl; class magicQuad {
C++ OpenGL: Вывести значения двух функций
Пытаюсь разобраться с opengl , хотел вывести две функции , но выдает ошибку , подскажите как исправить. #include <iostream> #include<openGL/gl.h> #include<Glut/glut.h> void draw() { glClear(GL_COLOR_BUFFER_BIT); glColor3f(1, 0, 0);
C++ Работа с динамическими символьными массивами и строками переменной длины http://www.cyberforum.ru/cpp-beginners/thread1497312.html
Здравствуйте! НЕ могу решить проблему из-за которой программа летит коту под хвост) Задача программы в том, чтобы по заранее заданным в поле номерам считать файлы с именами схожей конструкции: file1.dat .... file230.dat. То есть при каждой следующей итерации имя файла меняется, с ним производятся действия он закрывается. Поэтому требуется создавать массив имени файла. Проблема в том, что при...
C++ Что такое __pragma(warning()) ? Вот код макроса: #define PTM_WARNING_DISABLE \ __pragma(warning( push )) \ __pragma(warning( disable : 4867 )) Что эти функции делают? И что это за функция __pragma? От ее определение нельзя посмотреть? подробнее

Показать сообщение отдельно
Vlad1slav
21 / 21 / 5
Регистрация: 16.09.2009
Сообщений: 111
14.07.2015, 23:07  [ТС]     Специализация метода темплейтного класса вложенного в темплейтный класс
Цитата Сообщение от DrOffset Посмотреть сообщение
Из того, что я увидел (может конечно опять недостаток информации сказывается), мне сильно кажется, что он используется неправильно. А то, что он "работает" - просто вариация UB. Но это только предположение.
Цитата Сообщение от Vlad1slav Посмотреть сообщение
тут иделально подходит полиморфизм
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
struct Base
{
  virtual void f1() = 0;
  void f2() {}
  void f3() {}
};
 
struct Der1 : Base
{
  virtual void f1() {}
};
struct Der2 : Base
{
  virtual void f1() {}
};
Если бы я использовал полиморфизм я бы сделал так и не задумывался, но от него я решил отказаться и прищёл к статическому полиморфизму...

Если вправду так интересно, покажу что получилось...
Задача звучит так: нужно сделать хеш-мапу, которая позволила бы работать над ней нескольким потокам сразу. Я решил продублировать данные и писать сначала в одну часть, потом в другую, а читать из противоположных.
При этом ключ и значение должны существовать в единственном экземпляре а вспомогательные данные, такие как матрица списков(Array), список(Bucket), указатель на след. элемент списка(NextEntry) дублируются.

Всё написаное ниже является содержимым класса
template <typename Key, typename Value, typename Hash = std::hash<Key>, class Pred = std::equal_to<Key>>
class ConcurentHashMap
{
Entry declaration
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
    class Entry
      {
      public:
        Entry(const KeyType& i_key, const ValueType& i_value);
        ~Entry();
 
        void SetValue(const ValueType& i_value);
 
        const KeyType& GetKey() const;
        const ValueType& GetValue() const;
 
        Entry* GetFirstNextEntry() const;
        void SetFirstNextEntry(Entry* i_next_entry);
 
        Entry* GetSecondNextEntry() const;
        void SetSecondNextEntry(Entry* i_next_entry);
 
      private:
        Key m_key;
        Value m_value;
        Entry* mp_first_next;
        Entry* mp_second_next;
      };


Bucket declaration
Кликните здесь для просмотра всего текста
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
    template<typename Base>
    class Bucket
      {
      public:
        Bucket(Entry* ip_entries_head = nullptr);
 
        void Push(Entry* ip_new_entry, Entry* ip_hint_back_entry);
        void Remove(Entry* ip_entry, Entry* ip_hint_prev_entry);
 
        void Reset();
 
        bool IsEmpty() const;
 
        Entry* Front() const;
        Entry* Back() const;
 
        std::pair<Entry*, Entry*> Find(const KeyType& i_key) const;
 
      protected:
        ~Bucket() = default;
        Entry* mp_entries_head;
 
      private:
        static Entry* _IGetNextEntry(Entry* ip_entry);
        static void _ISetNextEntry(Entry* ip_entry, Entry* ip_next_entry);
      };
 
    class FirstBucket : public Bucket<FirstBucket>
      {
      public:
        FirstBucket() = default;
        FirstBucket(const FirstBucket& i_first_bucket) = delete;
        ~FirstBucket() = default;
        static Entry* GetNextEntry(Entry* ip_entry);
        static void SetNextEntry(Entry* ip_entry, Entry* ip_next_entry);
      };
 
    class SecondBucket : public Bucket<SecondBucket>
      {
      public:
        SecondBucket() = default;
        SecondBucket(const FirstBucket& i_first_bucket);
        ~SecondBucket();
        SecondBucket& operator=(const FirstBucket& i_first_bucket);
 
        static Entry* GetNextEntry(Entry* ip_entry);
        static void SetNextEntry(Entry* ip_entry, Entry* ip_next_entry);
      };


Bucket definition (only difference: GetNextEntry and SetNextEntry)
Кликните здесь для просмотра всего текста
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
template <typename Key, typename Value, typename Hash, class Pred>
template<typename Base>
typename ConcurentHashMap<Key, Value, Hash, Pred>::Entry* 
ConcurentHashMap<Key, Value, Hash, Pred>::Bucket<Base>::_IGetNextEntry(Entry* ip_entry)
  {
  return Base::GetNextEntry(ip_entry);
  }
 
template <typename Key, typename Value, typename Hash, class Pred>
template<typename Base>
void ConcurentHashMap<Key, Value, Hash, Pred>::Bucket<Base>::_ISetNextEntry(Entry* ip_entry, Entry* ip_next_entry)
  {
  return Base::SetNextEntry(ip_entry, ip_next_entry);
  }
 
/////////////////////////////////////////////////////////////////////////////////////
// class FirstBucket
/////////////////////////////////////////////////////////////////////////////////////
 
template <typename Key, typename Value, typename Hash, class Pred>
typename ConcurentHashMap<Key, Value, Hash, Pred>::Entry*
ConcurentHashMap<Key, Value, Hash, Pred>::FirstBucket::GetNextEntry(Entry* ip_entry)
  {
  return ip_entry->GetFirstNextEntry();
  }
 
template <typename Key, typename Value, typename Hash, class Pred>
void ConcurentHashMap<Key, Value, Hash, Pred>::FirstBucket::SetNextEntry(Entry* ip_entry, Entry* ip_next_entry)
  {
  ip_entry->SetFirstNextEntry(ip_next_entry);
  }
 
/////////////////////////////////////////////////////////////////////////////////////
// class SecondBucket
/////////////////////////////////////////////////////////////////////////////////////
 
template <typename Key, typename Value, typename Hash, class Pred>
typename ConcurentHashMap<Key, Value, Hash, Pred>::Entry*
ConcurentHashMap<Key, Value, Hash, Pred>::SecondBucket::GetNextEntry(Entry* ip_entry)
  {
  return ip_entry->GetSecondNextEntry();
  }
 
template <typename Key, typename Value, typename Hash, class Pred>
void ConcurentHashMap<Key, Value, Hash, Pred>::SecondBucket::SetNextEntry(Entry* ip_entry, Entry* ip_next_entry)
  {
  ip_entry->SetSecondNextEntry(ip_next_entry);
  }


С классом Bucket оказалось даже так, что функции типа f1(), а имеено GetNextEntry() и SetNextEntry() можно сделать статическими. _IGetNextEntry и _ISetNextEntry активно используются в остальных функциях класса Bucket<Base>.

Array declaration
Кликните здесь для просмотра всего текста
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
    template<typename Base, typename BucketType>
    class Array
      {
      public:
        Array(SizeType i_capacity = 16);
        
        SizeType GetCapacity() const;
 
        BucketType& operator[](size_t i_index);
        const BucketType& operator[](size_t i_index) const;
 
        const ValueType& GetValue(const KeyType& i_key) const;
        std::pair<bool, const ValueType*> Find(const KeyType& i_key) const;
        bool Contains(const KeyType& i_key) const;
 
        void lock();
        void unlock();
 
        void Wait();
 
        size_t CalcHash(const KeyType& i_key) const;
        SizeType CalcIndex(const KeyType& i_key) const;
 
      protected:
        ~Array();
 
        BucketType* mp_buckets;
        SizeType m_capacity;
 
      private:
        Hash m_hash;
        std::mutex m_conditional_mutex;
        std::atomic_int m_use_counter;
        std::condition_variable m_conditional_variable;
      };
 
    class FirstArray : public Array<FirstArray, FirstBucket>
      {
      public:
        FirstArray() = default;
        ~FirstArray() = default;
        void Clear();
        void Rehash();
      };
 
    class SecondArray : public Array<SecondArray, SecondBucket>
      {
      public:
        SecondArray() = default;
        ~SecondArray() = default;
        void Clear();
        void Rehash(const FirstArray& i_first_array);
      };


Array definition (only difference: Clear and Rehash)
Кликните здесь для просмотра всего текста
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
/////////////////////////////////////////////////////////////////////////////////////
// class FirstArray
/////////////////////////////////////////////////////////////////////////////////////
 
template <typename Key, typename Value, typename Hash, class Pred>
void ConcurentHashMap<Key, Value, Hash, Pred>::FirstArray::Clear()
  {
  for (SizeType i = 0; i < m_capacity; ++i)
    mp_buckets[i].Reset();
  }
 
template <typename Key, typename Value, typename Hash, class Pred>
void ConcurentHashMap<Key, Value, Hash, Pred>::FirstArray::Rehash()
  {
  const SizeType new_capacity = m_capacity << 1;
  FirstBucket* new_buckets = new FirstBucket[new_capacity];
 
  for (SizeType i = 0; i < m_capacity; ++i)
    {
    FirstBucket& bucket = mp_buckets[i];
    Entry* entry = bucket.Front();
    while (entry != nullptr)
      {
      Entry* next_entry = bucket.GetNextEntry(entry);
      bucket.SetNextEntry(entry, nullptr);
      FirstBucket& new_bucket = new_buckets[CalcHash(entry->GetKey()) & (new_capacity - 1)];
      new_bucket.Push(entry, new_bucket.Back());
      entry = next_entry;
      }
    bucket.Reset();
    }
 
  delete[] mp_buckets;
 
  m_capacity = new_capacity;
  mp_buckets = new_buckets;
  }
 
/////////////////////////////////////////////////////////////////////////////////////
// class SecondArray
/////////////////////////////////////////////////////////////////////////////////////
 
template <typename Key, typename Value, typename Hash, class Pred>
void ConcurentHashMap<Key, Value, Hash, Pred>::SecondArray::Clear()
  {
  for (SizeType i = 0; i < m_capacity; ++i)
    {
    delete mp_buckets[i].Front();
    mp_buckets[i].Reset();
    }
  }
 
template <typename Key, typename Value, typename Hash, class Pred>
void ConcurentHashMap<Key, Value, Hash, Pred>::SecondArray::Rehash(const FirstArray& i_first_array)
  {
  for (SizeType i = 0; i < m_capacity; ++i)
    mp_buckets[i].Reset();
  delete[] mp_buckets;
  
  m_capacity <<= 1;
  mp_buckets = new SecondBucket[m_capacity];
  for (SizeType i = 0; i < m_capacity; ++i)
    mp_buckets[i] = i_first_array[i];
  }

};

В Array'е пришлось применить ту же "стратегию", только из-за того что они содержат одинаковые данные и удалять данные должен только один из массивов.

Помойму это как раз таки тот случай, где именно необходимо применять static polymorphism. Лучшего примера для его применения я придумать не могу.
 
Текущее время: 23:27. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru