4

consider the following code :

struct X
{
    template <typename T>
    class Y
    {};
 };
template<>
class X::Y<double>{
};

here we are specializing the Y class for the type double and the code works fine. the problem is that if I change the code to this:

template<typename A>
struct X
{
    template <typename T>
    class Y
    {};
 };
template<typename A>
class X<A>::Y<double>{
};

the compiler will report an error:

'X::Y': explicit specialization is using partial specialization syntax, use template <> instead!

dose any one know how can I specialize class Y in this case?

MEMS
  • 617
  • 1
  • 6
  • 11
  • Does doing what the error message says not help? Use `template<>` instead of `template` on the nested template specialization. – Mark B Nov 15 '16 at 16:28
  • it dosen't work ! i tired this as well: template<> class X::Y{ }; – MEMS Nov 15 '16 at 16:30

2 Answers2

3

You cannot specialize an inner template class without explicitly specializing the outer one as well. See this question for more details and a quote from the standard.

Workaround: create an outer class that takes both T and A in a detail namespace, and alias it inside X:

namespace impl
{
    template <typename A, typename T>
    struct Y { };
}

template<typename A>
struct X
{
    template <typename T>
    using Y = impl::Y<A, T>;
};

If you are fine with explicitly specializing both inner and outer class, you can use the following syntax:

template <>
template <>
class X<int>::Y<double>
{
    // ...
};

Example on wandbox

Community
  • 1
  • 1
Vittorio Romeo
  • 90,666
  • 33
  • 258
  • 416
2

The simple answer - you can't fully specialize templated inner class of templated outer class. But if you really want to achieve similar effect you could try partial specialization with dummy defaulted template parameter:

#include <iostream>

template<typename A>
struct X
{
    template <typename T, T* =nullptr>
    class Y{};
 };

template<typename A>
template<double *Ptr>
class X<A>::Y<double, Ptr> {
public:
    static constexpr int value = 1;
};

int main() {
    std::cout << X<int>::Y<double>::value << std::endl;
}

[live demo]

W.F.
  • 13,888
  • 2
  • 34
  • 81
  • 1
    the book :Advanced metaprogramming in classic c++, on page 33 says: Template specializations are valid only at the namespace level: struct X { template class Y {}; template <> // illegal, but usually tolerated by compilers class Y {}; }; template <> // legal class X::Y { }; so what you have done might work but not always ! – MEMS Nov 15 '16 at 16:38
  • @MEMS You're author might be right. After looking for standards examples I've realized I might been actually over-interpreting the `[temp.class.spec] /5`. Updating code – W.F. Nov 15 '16 at 17:09
  • 1
    @MEMS according to C++ Standard Core Language Active Issues `727. In-class explicit specializations` inline partial specialization of member class is well formed... so my previous code was indeed valid. Please find the [reference](http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#727) – W.F. Nov 17 '16 at 12:07