Создание экземпляра шаблона класса с другим шаблоном класса приводит к использованию неполного типа - PullRequest
0 голосов
/ 19 марта 2020

Допустим, у нас есть следующие шаблоны классов:

template<size_t S>
struct A
{
  char str[S];
};

template<typename T>
class B
{
  T t;

public:
  void init(); // Should initialize the 't' member in some a way.
};

Теперь, если я специализирую init с некоторыми не шаблонными типами в качестве параметра шаблона B, все в порядке. Но я не могу специализировать его с A в качестве параметра B без указания его значения S. То есть я хотел бы сделать что-то вроде этого:

template<>
void B<A<S>>::init()
{
  // Initialize the 't.str'. For example:
  memset(t.str, 0, S);
}

Ответы [ 2 ]

2 голосов
/ 19 марта 2020

Чтобы обеспечить частичную специализацию, которая выполняет что-то, специфицирующее от c до B<A<???>>, вам необходимо предоставить такую ​​частичную специализацию для класса:

#include <cstddef>
#include <cstring>
#include <iostream>

template<std::size_t S>
struct A
{
  char str[S];
};

template<typename T>
class B
{
  T t;

public:
  void init(); // Should initialize the 't' member in some a way.
};

template<std::size_t S>
class B<A<S>> {
  using T = A<S>;

  T t;

public:
  void init(); // Should initialize the 't' member in some a way.
};

template<std::size_t S>
void B<A<S>>::init()
{
  // Initialize the 't.str'. For example:
  std::memset(t.str, 0, S);
  std::cout << "Initialized B<A<" << S << ">>\n";
}

int main() {
    B<A<3>> b;
    b.init();
}

Обратите внимание, что есть два ключевых различия к вашему коду:

  1. Существует частичная специализация шаблона класса template<std::size_t S> class B<A<S>>
  2. Функция-член init этого шаблона класса теперь может быть определена как template<std::size_t> void B<A<S>>::init() { /* ... */ }

Вы можете опустить определение базового случая шаблона класса B и заменить его на template<typename T> class B;, если в вашем случае использования нет других экземпляров.

см. это жить

0 голосов
/ 19 марта 2020

Поскольку структура A должна отвечать за создание и уничтожение ее членов, я предлагаю вам сделать следующее:

template <size_t S = 5>
struct A {
    A() {
        memset(str, 0, S);
    }

    char str[S];
};

и тогда вы можете иметь:

template<>
void B<A<>>::init()
{}

ОБНОВЛЕНИЕ

Как указал @NathanOliver, конструктор по умолчанию для struct A даже не нужен. Следующее тоже будет работать:

template <size_t S = 5>
struct A {
    char str[S]{};
};

и, поскольку ответственность за инициализацию массива char передается в struct A, не требуется специализация шаблона.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...