派生类中类模板的部分特化会影响基类
Posted
技术标签:
【中文标题】派生类中类模板的部分特化会影响基类【英文标题】:Partial specialization of a class template in derived class affects base class 【发布时间】:2009-09-11 20:42:01 【问题描述】:我有一个元函数:
struct METAFUNCION
template<class T>
struct apply
typedef T type;
;
;
然后我定义一个助手:
template<class T1, class T2>
struct HELPER
;
然后我有第二个元函数,它派生自上面的 METAFUNCTION 并定义了应用结构的部分特化:
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 结构中应用结构的内容)。
所以我的问题是 - 这个 g++ 行为是否符合标准?我有一种强烈的感觉,这里有问题,但我不是 100% 确定。
出于好奇 - 当我以这种方式重新定义 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>
;
;
【问题讨论】:
这不是你的真实代码,因为template<class T1, class T2> struct apply<HELPER<T1, T2> > : METAFUNCION::apply<T2> ;
不会编译。我不再在那里阅读你的问题了。
很遗憾您没有指定您使用的编译器和版本。我已经非常清楚地表明该代码可以在 g++ 4.3.2 上编译并且不能在 VC++ 2008 上编译。
@Tomek:我使用的是 Brain 1.0。 :)
代码完全错误。很抱歉过早地忽略了您的问题,但是这里的问题中粘贴了太多错误的代码,以至于当错误成为问题的核心时,我养成了停止打扰的习惯。我不敢相信,gcc4 会出错...
据我了解这个问题,不过,他并没有声称代码是正确的。他问哪个编译器是正确的。我也提出过这样的问题。我用 gcc4.4 进行了测试,是的,它弄错了(至少,与 Comeau 不同,它本身说了很多哈哈)。
@lib:他写了“代码在g++ 4.3.2下编译”。我不相信。我错了。这就是我说对不起的原因。
【参考方案1】:
所以我提交了a bug on gcc
【讨论】:
我相信你的标准引用并不适用,因为你没有声明一个明确的特化(你是在声明和定义一个部分特化),并且因为类模板的声明是特化的i>已经在范围内。不过,我还没有找到一个明确的要求,即成员模板的部分特化应该是同一类的成员。 好吧,VC++ 拒绝代码,所以至少有一些事情需要考虑。正如我所写 - 我不希望部分专业化来处理继承树。至少当我“发明”那段代码时,我是这样想的。 @Tomek,这里有同样的怀疑 :) 我也不认为部分专业化应该在树上起作用。主要和部分特化模板都是同一模板的“替代定义”(原始措辞),因此它们应该在同一类范围内为模板提供定义,而不是在派生类范围内(这意味着定义发生在模板声明之外的另一个范围)。但我希望在标准中明确引用这一点。 对于追随者,我刚刚收到一封来自 gcc bugzilla 的电子邮件,说此错误已在 gcc 4.5.0 中修复。【参考方案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,此限制不适用于成员模板的部分特化。
【讨论】:
目前还不清楚是否可以在其派生类中专门化基类的内部模板,以及它是否应该仅在派生类或基类中可见。以上是关于派生类中类模板的部分特化会影响基类的主要内容,如果未能解决你的问题,请参考以下文章