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

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

Восстановить пароль Регистрация
 
Vlad1slav
21 / 21 / 5
Регистрация: 16.09.2009
Сообщений: 111
11.07.2015, 21:21     Специализация метода темплейтного класса вложенного в темплейтный класс #1
Есть два темплейтных класса
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
template <bool T2>
class B
{
  void b();
}
 
template <>
void B<true>::b() {}
 
template <>
void B<false>::b() {}
 
template <typename T1>
class A
{
  void a();
  B _b;
}
В таком виде всё работает отлично, но хотелось бы скрыть класс B, т.к. он является вспомогательным для класса A, и нигде снаружи в нём нет необходимости... т.е. написать что-то типо

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
template <typename T1>
class A
{
  void a();
 
  template <bool T2>
  class B
  {
    void b();
  }
 
  B _b;
}
 
template <T1>
template <>
void A<T1>::B<true>::b() {}
 
template <T1>
template <>
void A<T1>::B<false>::b() {}
Но компилятор ругается.
Говорит C3855: 'class B': type parameter 'T2' is incompatible with the declaration.
Как-то можно это обойти и сделать класс B вложенным в класс A?
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
11.07.2015, 21:21     Специализация метода темплейтного класса вложенного в темплейтный класс
Посмотрите здесь:

Может ли объемлющий класс иметь неограниченный доступ к элементам вложенного класса? А вложенный класс — к элементам объемлющего? C++
В конструкторе вложенного класса инициализируется приватное поле. Потом вызывается функция-метод этого класса и выводит значение этого поля НО НЕ ТО! C++
C++ Явная специализация класса
C++ Передача метода класса в качестве параметра для метода другого класса
C++ Специализация шаблона класса
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
ct0r
C++/Haskell
 Аватар для ct0r
1549 / 568 / 39
Регистрация: 19.08.2012
Сообщений: 1,174
Завершенные тесты: 1
12.07.2015, 01:31     Специализация метода темплейтного класса вложенного в темплейтный класс #2
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от Vlad1slav Посмотреть сообщение
Как-то можно это обойти и сделать класс B вложенным в класс A?
Не самая удачная идея. Предлагаю поместить класс В в анонимное или details пространство имен.
Vlad1slav
21 / 21 / 5
Регистрация: 16.09.2009
Сообщений: 111
12.07.2015, 01:45  [ТС]     Специализация метода темплейтного класса вложенного в темплейтный класс #3
ct0r, Пожалуй так и сделаю...

Как оказалось, специализировать класс B можно только в случае полной специализации класса А.

Хотя студия позволяет такое сделать...
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
template <typename T1>
class A
  {
  public:
    A() {}
  template <bool T2>
  class B;
 
  template<>
  class B<true>
    {
    public:
    void f() { /* Do smg */ }
    };
 
  template<>
  class B<false>
    {
    public:
    void f() { /* Do smg else */ }
    };
  };
но это не по стандарту, вынести определение за пределы объявления класса не удаётся, а др. компиляторы вообще ругаются на такое.
DrOffset
6461 / 3835 / 885
Регистрация: 30.01.2014
Сообщений: 6,630
12.07.2015, 03:38     Специализация метода темплейтного класса вложенного в темплейтный класс #4
Цитата Сообщение от Vlad1slav Посмотреть сообщение
Как оказалось, специализировать класс B можно только в случае полной специализации класса А.
Можно выкрутиться и специализировать класс B частично, тогда все будет в рамках стандарта.
Для этого надо добавить один фиктивный параметр по умолчанию:
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 <typename T1>
class A
{
public:
  A() {}
  
  template <bool T2, typename = void>
  class B;
 
  template <typename Dummy>
  class B<true, Dummy>
  {
  public:
      void f() { /* Do smg */ }
  };
 
  template <typename Dummy>
  class B<false, Dummy>
  {
  public:
      void f() { /* Do smg else */ }
  };
};
http://rextester.com/COG21607
Vlad1slav
21 / 21 / 5
Регистрация: 16.09.2009
Сообщений: 111
12.07.2015, 11:48  [ТС]     Специализация метода темплейтного класса вложенного в темплейтный класс #5
DrOffset, абалдеть, и вправду работает)
Но к сожалению это не совсем то что мне нужно.

Мой класс B содержит порядка 10 методов и почти все они совпадают, но есть парочку, которые различаются. Специально для них и решил использовать темплейты со специальизациями.
Теперь чтобы объявить и определить их всех для случаев true и false, прийдётся продублировать код:
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
template <typename T1>
class A
{
public:  
  template <bool T2, typename = void>
  class B;
 
  template <typename Dummy>
  class B<true, Dummy>
  {
  public:
      void f1(); /* Do smg1 */
      void f2(); /* Do smg2 */
      void f3(); /* Do smg3 */
  };
 
  template <typename Dummy>
  class B<false, Dummy>
  {
  public:
      void f1(); /* Do smg1_else */
      void f2(); /* Do smg2 */
      void f3(); /* Do smg3 */
  };
};
//и затем дважды продублировать определения.
В конечном итоге можно тоже самое написать и без темплейтов:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
template <typename T1>
class A
{
public:
  A() {}
   
  class B1
  {
  public:
      void f1(); /* Do smg1 */
      void f2(); /* Do smg2 */
      void f3(); /* Do smg3 */
  };
 
  class B2
  {
  public:
      void f1(); /* Do smg1_else */
      void f2(); /* Do smg2 */
      void f3(); /* Do smg3 */
  };
};
Хотелось бы всё общее определить без частичной спецификации, а методы, которые имеют различия - уже со спецификацией, приблизительно так:
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
template <typename T1>
class A
{
public:  
  template <bool T2, typename = void>
  class B  
  {
    public:
    void f2();
    void f3();
  };
 
  template <typename Dummy>
  class B<true, Dummy>
  {
    public:
    void f1();
  };
  
  template <typename Dummy>
  class B<false, Dummy>
  {
    public:
    void f1();
  };
};
 
template <typename T1>
template <typename Dummy>
void A<T1>::B<true, Dummy>::f1()
{  
}
 
template <typename T1>
template <typename Dummy>
void A<T1>::B<false, Dummy>::f1()
{  
}
 
template <typename T1>
template <bool T2, typename Dummy>
void A<T1>::B<T2, Dummy>::f2()
{
}
 
template <typename T1>
template <bool T2, typename Dummy>
void A<T1>::B<T2, Dummy>::f3()
{
}
 
int main()
{
    A<int>::B<true> b1;
    b1.f1();
    b1.f2(); // error: A<int>::B<true> has no member f2
    b1.f3(); // error: A<int>::B<true> has no member f3
    A<int>::B<false> b2;
    b2.f1();
    b2.f2(); // error: A<int>::B<false> has no member f2
    b2.f3(); // error: A<int>::B<false> has no member f3
}
http://rextester.com/ZKRHS10208

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

Раз такой код не компилиться, буду обходиться namespac'ами.

Если есть идеи как сделать это по другому - буду рад выслушать.

Добавлено через 1 час 5 минут
Как я сразу не догодался... Тут можно использовать Static polymorphism:

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
template <typename T1>
struct A
{
  template<typename T2>
  struct BaseB
  {
    void f1();
    void f2();
    void f3();
  };
 
  struct B_true : BaseB<B_true>
  {
    void f1_impl();
  };
  
  struct B_false : BaseB<B_false>
  {
    void f1_impl();
  };
};
 
template <typename T1>
template<typename T2>
void A<T1>::BaseB<T2>::f1()
{
  static_cast<T2*>(this)->f1_impl();
}
 
template <typename T1>
template<typename T2>
void A<T1>::BaseB<T2>::f2()
{
  
}
 
template <typename T1>
template<typename T2>
void A<T1>::BaseB<T2>::f3()
{
  
}
 
template <typename T1>
void A<T1>::B_true::f1_impl()
{
  
}
 
template <typename T1>
void A<T1>::B_false::f1_impl()
{
  
}
 
int main()
{
  A<char>::B_true b_true;
  b_true.f1();
  b_true.f2();
  b_true.f3();
  
  A<char>::B_false b_false;
  b_false.f1();
  b_false.f2();
  b_false.f3();
}
http://rextester.com/XXWK48117

Это то что мне было нужно)
DrOffset
6461 / 3835 / 885
Регистрация: 30.01.2014
Сообщений: 6,630
13.07.2015, 13:47     Специализация метода темплейтного класса вложенного в темплейтный класс #6
Цитата Сообщение от Vlad1slav Посмотреть сообщение
Это то что мне было нужно)
Ага. Идиома называется CRTP.

А вообще, последний пост автора как раз хорошо свидетельствует о том, насколько важно сразу детально описывать свою задачу
Хорошо заданный вопрос - половина ответа (а то и весь).

Добавлено через 23 часа 42 минуты
Цитата Сообщение от Vlad1slav Посмотреть сообщение
Это то что мне было нужно)
Кстати, этот пример, который является "тем, что нужно" очень легко использовать неправильно. Я не говорю, что именно в этом случае он так используется, но эту задачу можно решить лучше.
Первый вариант:
Кликните здесь для просмотра всего текста
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
template <typename T1>
class A
{
public:
   class Base
   {
   public:
       void f2(); /* Do smg2 */
       void f3(); /* Do smg3 */
   };
 
   template <bool, typename = void>
   class B : public Base
   {
   public:
       void f1(); /* Do smg1 */
   };
 
   template <typename Dummy>
   class B<false, Dummy> : public Base
   {
   public:
       void f1(); /* Do smg1_else */
   };
};

Второй вариант (наоборот):
Кликните здесь для просмотра всего текста
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
template <typename T1>
class A
{
public:
   template <bool F, typename = void>
   struct Base
   {
       void f1(); /* Do smg1 */
   };
 
   template <typename Dummy>
   struct Base<false, Dummy>
   {
       void f1(); /* Do smg1 else */
   };
 
   template <bool F>
   class B : Base<F>
   {
   public:
       using Base<F>::f1;
 
       void f2(); /* Do smg2 */
       void f3(); /* Do smg3 */
   };
};

При этом работаем мы всегда с типом B. Base как бы за кадром.
Vlad1slav
21 / 21 / 5
Регистрация: 16.09.2009
Сообщений: 111
14.07.2015, 00:53  [ТС]     Специализация метода темплейтного класса вложенного в темплейтный класс #7
DrOffset, первый вариант однозначно не подходит, по причине, которую, опять таки, я не указал...
Дело в том, что функция f1() используется в функциях f2() и f3().
Во втором случае, можно ли вынести определение классы за пределы объявления? У меня никак не получается... Если можно-тогда да, второй вариант тоже бы подошёл. Но в целом меня и ститический полиморфизм вполне устроил.
DrOffset
6461 / 3835 / 885
Регистрация: 30.01.2014
Сообщений: 6,630
14.07.2015, 01:07     Специализация метода темплейтного класса вложенного в темплейтный класс #8
Цитата Сообщение от Vlad1slav Посмотреть сообщение
Но в целом меня и ститический полиморфизм вполне устроил.
Из того, что я увидел (может конечно опять недостаток информации сказывается), мне сильно кажется, что он используется неправильно. А то, что он "работает" - просто вариация UB. Но это только предположение.

Цитата Сообщение от Vlad1slav Посмотреть сообщение
У меня никак не получается...
Все выносится хорошо:
Кликните здесь для просмотра всего текста
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
template <typename T1>
class A
{
public:
   template <bool F, typename = void>
   struct Base
   {
       void f1(); /* Do smg1 */
   };
 
   template <typename Dummy>
   struct Base<false, Dummy>
   {
       void f1(); /* Do smg1 else */
   };
 
   template <bool F>
   class B : Base<F>
   {
   public:
       using Base<F>::f1;
 
       void f2(); /* Do smg2 */
       void f3(); /* Do smg3 */
   };
};
 
template <typename T1>
template <bool F, typename Dummy>
void A<T1>::Base<F, Dummy>::f1()
{
}
 
template <typename T1>
template <typename Dummy>
void A<T1>::Base<false, Dummy>::f1()
{
}
 
 
template <typename T1>
template <bool F>
void A<T1>::B<F>::f2()
{
}
 
template <typename T1>
template <bool F>
void A<T1>::B<F>::f3()
{
}

http://rextester.com/SRJTH62470
Vlad1slav
21 / 21 / 5
Регистрация: 16.09.2009
Сообщений: 111
14.07.2015, 23:07  [ТС]     Специализация метода темплейтного класса вложенного в темплейтный класс #9
Цитата Сообщение от 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. Лучшего примера для его применения я придумать не могу.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
15.07.2015, 00:07     Специализация метода темплейтного класса вложенного в темплейтный класс
Еще ссылки по теме:

C++ Явная специализация шаблонного класса
C++ Сложности с переносом метода из класса в класс
Вызов метода производного класса через указатель на базовый класс C++

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

Или воспользуйтесь поиском по форуму:
DrOffset
6461 / 3835 / 885
Регистрация: 30.01.2014
Сообщений: 6,630
15.07.2015, 00:07     Специализация метода темплейтного класса вложенного в темплейтный класс #10
Цитата Сообщение от Vlad1slav Посмотреть сообщение
Помойму это как раз таки тот случай
Да, тут все чисто. Спасибо

Не по теме:

Очень сложно сразу определить "уровень" человека, который задает тут вопрос. Поэтому я сперва предполагаю худшее. Не принимай на свой счет

Yandex
Объявления
15.07.2015, 00:07     Специализация метода темплейтного класса вложенного в темплейтный класс
Ответ Создать тему
Опции темы

Текущее время: 13:59. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru