Почему я могу частично специализироваться, но не могу полностью специализировать шаблоны элементов в C ++? - PullRequest
0 голосов
/ 07 июня 2018

IMO, правила шаблона C ++ кажутся слишком строгими, и реализация компилятора определена.Но здесь у меня есть определенное поведение, с которым мне трудно было обернуться.

В следующей задаче я сознательно стараюсь избегать явной специализации родительского класса.

Проблема в том, что я могу частично специализировать участника, но не могу специализировать его полностью.Что действительно противоречит интуиции, потому что вы можете легко добавить фиктивный шаблон в полностью специализированный шаблон и сделать его частично специализированным.Что здесь происходит ??

Важное редактирование: это важно, потому что, как мы знаем, вы не можете специализировать функции-члены, не специализируя также и класс (что можно рассматривать как комбинацию этой проблемы, необходимобыть частично специализированным, и тот факт, что c ++ не допускает частично специализированные функции. Я не знаю, связаны ли они, но, по крайней мере, они согласованы), поэтому, если вы хотите, чтобы в вашем классе был функционал, вы можете специализировать себя »Застрял с использованием функторов.И вдобавок к этому вам нужно добавить фиктивный параметр шаблона, просто чтобы заставить это работать !!

Это работает:

template <class T>
class A
{
  template<typename Y, typename Z>
  struct C{
      void operator()(int x);
  };

  template<typename Z>
  struct C<int, Z>{
      void operator()(int x);
  };
};

template <class T>
template <typename Z>
void A<T>::C<int, Z>::operator()(int x){

}

Но это не так:

template <class T>
class A
{
  template<typename Y>
  struct C{
      void operator()(int x);
  };

  template<>
  struct C<int>{
      void operator()(int x);
  };
};

template <class T>
template <>
void A<T>::C<int>::operator()(int x){

}

Редактировать: Шон Ф. в комментариях указал, что компилятору сложно выбрать специализацию.Но проблема здесь в том, что частичная специализация не устраняет эту проблему.Так что это не может быть ответом.

1 Ответ

0 голосов
/ 07 июня 2018

Как правило, специализация шаблонных функций - плохая идея.Используйте перегрузки или диспетчеризацию тегов.Например:

template<class T>struct tag_t{};

template<class T>
auto foo(T& t){ return foo( tag_t<T>{}, t ); }

теперь мы можем использовать перегрузки для отправки:

void foo( tag_t<int>, int& i ){ i+=3; }
template<class T>
void foo( tag_t<T>, T& t ){ t*=2; }

здесь никакой специализации не происходит.Мы используем правила разрешения перегрузки, чтобы выбрать реализацию.И это прекрасно работает с членами.

Мы используем специализацию только на классах верхнего уровня.Даже там я часто испытываю искушение выбирать реализации с помощью диспетчеризации тегов и использования decltype, поскольку разрешение перегрузки часто дает лучшее сопоставление с образцом.

Если вам действительно нужен класс-член, замените свой класс-член классом верхнего уровняи некоторые заявления друзей.

template<class T, class Y>
struct A_C;
template <class T>
class A
{
  template<class T0, class Y0>
  friend class A_C<T0, Y0>;
  template<class Y>
  using C=A_C<T,Y>;
};
template<class T, class Y>
struct A_C {
  // implementation of A::C
};

теперь у вас есть довольно неограниченная специализация A_C здесь.Ни одна из ваших проблем.

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