Как избежать "шаблонных параметров, не выводимых при частичной специализации" - PullRequest
0 голосов
/ 25 февраля 2019

Я хотел бы иметь доступ к вложенному классу с помощью шаблонов и не могу понять, как это сделать: Пример кода:

template <typename T> class mything {
  typedef unsigned key;
  T data;
public:
  template <typename subT> class mysubthing { typedef subT value_type; };
  using subthing = mysubthing<T>;
  using subthing_ro = mysubthing<const T>;
};

template<typename T> struct X; // a container for all value_types

#ifdef MAKE_IT_FAIL
// this should automatically set the X<mything<T>::mysubthing<subT>
template<typename T,typename subT> struct X<typename mything<T>::template mysubthing<subT>> {
  using value_type = subT;
};
#endif

typedef mything<int> intthing;

#ifndef MAKE_IT_FAIL
template<> struct X<mything<int>::subthing> { using value_type = int; };
template<> struct X<mything<int>::subthing_ro> { using value_type = const int; };
#endif

int main(void) {
  intthing t;
  X<intthing::subthing>::value_type data = 1; // a data object
  X<intthing::subthing_ro>::value_type data_ro = 1; // read-only data object

  return 0;
}

Это компилируется без -DMAKE_IT_FAIL, но, конечно, этополностью упускает пункт о шаблонах, так как то, что я хотел, было введено вручную.Как я могу заставить его работать с -DMAKE_IT_FAIL?

1 Ответ

0 голосов
/ 25 февраля 2019

Вы не можете специализироваться таким образом:

template<typename T,typename subT> 
struct X<typename mything<T>::template mysubthing<subT>> {

, так как вычитание T из типов, таких как outer<T>::anything_after, невозможно (не поддерживается) в C ++.

Вы на самом деле этого не делаетенужна специализация в этом общем случае вообще.Просто определите X по умолчанию, а затем специализируйте только другие случаи:

template <typename T> class mything {
  typedef unsigned key;
  T data;
public:
  template <typename subT> struct mysubthing 
  { 
      typedef subT value_type; 

  };
  using subthing = mysubthing<T>;
  using subthing_ro = mysubthing<const T>;
};

template<typename T> struct X
{
   using value_type = typename T::value_type;
};
// this should automatically set the X<mything<T>::mysubthing<subT>

typedef mything<int> intthing;

template<> struct X<mything<int>::subthing> { using value_type = int; };
template<> struct X<mything<int>::subthing_ro> { using value_type = const int; };

int main(void) {
  intthing t;
  X<intthing::subthing>::value_type data = 1; // a data object
  X<intthing::subthing_ro>::value_type data_ro = 1; // read-only data object

  return 0;
}

Приложение

Согласно одному из комментариев, X на самом деле std::iterator_traits, который уже определен.В этом случае единственный способ обойти это - определить класс итератора вне класса mything:

template <typename T, typename subT>
class mything_iterator {
   typedef subT value_type; 
};
template <typename T> class mything {
      typedef unsigned key;
      T data;
    public:
      using iterator = mything_iterator<T, T>;
      using const_iterator = mything_iterator<T, const T>;
};
namespace std {
   template<typename T, class subT>
   class iterator_traits<mything_iterator<T, subT>>{
       using value_type =typename  mything_iterator<T, subT>::value_type;
       // etc...
   };
   template<> struct iterator_traits<mything<int>::iterator>
   { using value_type = int; };
   template<> struct iterator_traits<mything<int>::const_iterator>
   { using value_type = int; };
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...