Вы не можете специализироваться таким образом:
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; };
}