派生类中类模板的部分特化会影响基类

时间:2009-09-11 20:42:01

标签: c++ templates g++ metaprogramming

我有一个元函数:

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

然后我定义了一个帮手:

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

然后我有第二个元函数,它来自上面的METAFUNCTION并定义了apply struct的部分特化:

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

到目前为止,这么好 - 代码在g ++ 4.3.2下编译。所以我用它如下:

#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);
}

输出:

int
double
double

这让我感到惊讶,就像我预料的那样:

int
HELPER<float, double>
double

现在,我知道上面的代码不能在Microsoft Visual C ++ 2008下编译(我不记得这条消息,但我不能专门在METAFUNCTION2 struct中应用struct)。

所以我的问题是 - 这个g ++行为符合标准吗?我有一种强烈的感觉,这里有问题,但我不是百分百肯定。


对于好奇的人 - 当我以这种方式重新定义METAFUNCTION2时,我的行为正如我预期的那样:

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

2 个答案:

答案 0 :(得分:3)

所以我提交了a bug on gcc

答案 1 :(得分:2)

以下代码是非法的:

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

根据C ++标准14.7.3 / 3:

  

明确专门化的函数模板或类模板的声明应在范围内   明确专业化的声明点。

编辑:根据Core Issue 727,此限制不适用于成员模板的部分专业化。