Partial specialization of a class template in deri

2019-07-23 09:50发布

问题:

I have a metafunction:

struct METAFUNCION
{
  template<class T>
  struct apply
  {
    typedef T type;
  };
};

Then I define a helper:

template<class T1, class T2>
struct HELPER
{
};

And then I have second metafunction which derives from the METAFUNCTION above and defines partial specialization of apply struct:

struct METAFUNCION2 : METAFUNCION
{
  template<class T1, class T2>
  struct apply<HELPER<T1, T2> > : METAFUNCION::apply<T2>
  {
  };
};

So far, so good - the code compiles under g++ 4.3.2. So I used it like below:

#include <typeinfo>
#include <string>
#include <cstdlib>
#include <cxxabi.h>

template<typename T>
struct type_info2
{
  static std::string name()
  {
    char *p = abi::__cxa_demangle(typeid(T).name(), 0, 0, 0);
    std::string r(p);
    free(p);
    return(r);
  }
};

#include <boost/mpl/apply.hpp>
#include <iostream>

int main()
{
  std::cout <<
    type_info2<boost::mpl::apply<METAFUNCION, int>::type>::name() <<
    std::endl;
  std::cout <<
    type_info2<boost::mpl::apply<METAFUNCION, HELPER<float, double> >::type>::name() <<
    std::endl;
  std::cout <<
    type_info2<boost::mpl::apply<METAFUNCION2, HELPER<float, double> >::type>::name() <<
    std::endl;
  return(0);
}

The output:

int
double
double

That surprised me a bit as I expected:

int
HELPER<float, double>
double

Now, I know that code like above does not compile under Microsoft Visual C++ 2008 (I don't remeber the message but it was something along the lines that I cannot specialize apply struct inside METAFUNCTION2 struct).

So my question is - is this g++ behaviour conformant with the standard? I have a strong feeling that there is something wrong here but I am not 100% sure.


For the curious - I have the behaviuor as I expected when I redefine METAFUNCTION2 this way:

struct METAFUNCION2 : METAFUNCION
{
  template<class T>
  struct apply : METAFUNCION::apply<T>
  {
  };
  template<class T1, class T2>
  struct apply<HELPER<T1, T2> > : METAFUNCION::apply<T2>
  {
  };
};

回答1:

The following code is illegal:

struct METAFUNCION2 : METAFUNCION
{
  template<class T1, class T2>
  struct apply<HELPER<T1, T2> > : METAFUNCION::apply<T2>
  {
  };
};

According to C++ Standard 14.7.3/3:

A declaration of a function template or class template being explicitly specialized shall be in scope at the point of declaration of an explicit specialization.

EDIT: According to Core Issue 727 this restriction does not apply to partial specializations of member templates.



回答2:

So I filed a bug on gcc