模板部分专业化

时间:2011-03-06 15:00:16

标签: c++ templates

根据下面的规则,任何人都知道不编译吗?

template <class T>
struct B
{
    typedef T type;
};

template<class T>
struct X
{
};
template<class T>
struct X<B<T>::type*>//HERE I'M PARTIALLY SPECIALIZING (WELL, TRYING TO...)
{
};

请参阅代码内的评论。

3 个答案:

答案 0 :(得分:9)

您认为这会如何运作?编译器会查看某个类的某个类是否有类型为typedef“type”的类?

它不会。即使它是一个指针。

请记住,大概你的B模板可能在某些地方是专用的,因此类型并不总是T *,但它不能通过逆向工程来推断它。

对于那些完全不理解我的答案的人,你要求编译器做的是找到一个类U,这样B :: type就是你作为参数传入的类。

class Foo;
class Bar;

template<> struct B<Foo>
{
  typedef int type;
};

template<> struct B<Bar>
{
  typedef int type;
};

X<int*> // ambiguous, T is Foo or Bar?

很难确切地知道你为什么要做你想做的事。你可以对所有指针进行部分特化,然后对特定指针进行全面的特化,这可以用另一个模板来实现。

答案 1 :(得分:4)

您需要使用typename关键字作为

template<class T>
struct X<typename B<T>::type*>
{
};

这是因为B<T>::type是一个从属名称。所以typename是必需的!

-

编辑:

即使在放置typename之后,它也没有编译。我认为这是因为从T B<T>中删除X<U>类型对于编译器来说很难或者可能是不可能的。所以我相信它的非推断背景。

在此处查看类似示例和讨论:

Template parameters in non-deduced contexts in partial specializations


但是,如果您将专业化更改为:

template<class T>
struct X<B<T> >
{
};

然后它成为可推导的上下文,因此编译。

答案 2 :(得分:0)

假设您已根据Nawaz的建议添加了typename

问题在您遇到的错误消息中得到了解释:“模板参数在部分特化B<T>::type*中无法推导。问题是B<T>::typeT完全相同所有类型T。请考虑以下示例:

class MyClass1 {};
typedef typename B<MyClass>::type MyClass2; //(*)

X<MyClass*> obj1;
X<MyClass2*> obj2;

(*)的结果是MyClass2类型,它本质上是MyClass1。因此,obj1obj2应该是同一个类的对象。现在,他们应该使用哪个版本的模板X

如果你期望X的专业版,请告诉我,如果删除了行(*),答案应该是相同的(显然obj2也是如此)。仍然obj1应该是X的专用版本,因为行(*)与它无关。

但是现在我们希望编译器检测到某些类型可能被声明为B<T>::type,尽管我们从未这样做过。我们希望编译器验证所有可能的模板实例,以检查其中一个是否存在奇怪的typedef。

我希望这可以澄清为什么编译器无法处理这种专业化。


可能有帮助的替代方案

我相信你的问题可能会受到攻击,因为它创建了一个特性类来明确标记应该以特殊方式处理的类型。像这样:

template <bool v>
struct boolean_value {
  static const bool value=v;
};

template <typename T>
struct is_my_interesting_type : public boolean_value<false> {};

class MyClass {
  ...
};

template <>
struct is_my_interesting_type<MyClass> : public boolean_value<true> {};

template <typename T, bool special>
class  InternalX {
  ... //generic version of your template X
};

template <typename T>
class InternalX<T,true> {
  ... //special version of your template X
};

template <typename T>
class X : public InternalX<T,is_my_interesting_type<T>::value> {};

此外,您可能会对如何在boost库中完成它感兴趣,特别是Boost.Type_Traits