【问题标题】:Template specialization with a templatized type具有模板化类型的模板特化
【发布时间】:2009-11-25 14:45:10
【问题描述】:

我想专门化一个具有以下功能的类模板:

template <typename T>
class Foo
{
public:
    static int bar();
};

该函数没有参数,并应根据 Foo 的类型返回结果。 (在这个玩具示例中,我们返回类型的字节数,但在实际应用程序中,我们希望返回一些元数据对象。) 专业化适用于完全指定的类型:

// specialization 1: works
template <>
int Foo<int>::bar() { return 4; }

// specialization 2: works
template <>
int Foo<double>::bar() { return 8; }

// specialization 3: works
typedef pair<int, int> IntPair;
template <>
int Foo<IntPair>::bar() { return 2 * Foo<int>::bar(); }

但是,我想将其推广到依赖于(其他)模板参数本身的类型。 添加以下特化会导致编译时错误(VS2005):

// specialization 4: ERROR!
template <>
template <typename U, typename V>
int Foo<std::pair<U, V> >::bar() { return Foo<U>::bar() + Foo<V>::bar(); }

我假设这不是合法的 C++,但为什么呢?有没有办法优雅地实现这种模式?

【问题讨论】:

  • 但是请注意,返回 T:static int Foo() { return sizeof(T); } 的大小不需要任何特化。我想知道这种模式是否对你真正的问题没有帮助。

标签: c++ templates specialization


【解决方案1】:

部分特化仅对类有效,对函数无效。

解决方法:

template <typename U, typename V>
class Foo<std::pair<U, V> > { 
public:
 static int bar() { return Foo<U>::bar() + Foo<V>::bar(); }
};

如果您不想完全专门化类,请使用辅助结构

template<class T>
struct aux {
  static int bar();
};

template <>int aux <int>::bar() { return 4; }
template <>int aux <double>::bar() { return 8; }

template <typename U, typename V>
struct aux <std::pair<U, V> > { 
  static int bar() { return Foo<U>::bar() + Foo<V>::bar(); }
};

template<class T>
class Foo : aux<T> {
  // ... 
};

【讨论】:

  • 在这个例子中,所有的特化都是类特化
  • 是的。对。禁止函数部分专门化。只能为功能栏创建基类。
  • @TimW,在问题中,诀窍在于该类不是专门的。这超出了标准:“类模板的成员函数、成员类或静态数据成员可能被显式特化为隐式实例化的类特化;如果类模板成员的这种显式特化隐式声明的特殊成员函数(第 12 条),程序格式错误。”。它是该模板的一个给定隐式实例化(因此,没有模板参数依赖)的特化(不是任何部分特化)。
  • @litb 因此,如果他没有编写专门的类定义,那么他的程序是不正确的。我只是假设他只是将它们排除在示例之外
  • 很好的解释和解决方法。然而,解决方法是有限的,因为有时必须专门化现有的类。例如,我必须专门化 boost::numeric::interval_lib::checking_base&lt;T&gt; 的单个 static 函数,为此我必须复制整个类只是为了更改一点 boost::numeric::interval_lib::checking_base&lt;T&gt;::empty_lower()。 (顺便说一下,当T 匹配quantity&lt;U&gt; 时,我需要特别注意。)
【解决方案2】:

这在 C++ 中是完全合法的,它是部分模板特化。
删除template &lt;&gt;,如果它不存在,添加明确的类模板特化,它应该在VS2005上编译(但不是在VC6中)

// explicit class template specialization
template <typename U, typename V>
class Foo<std::pair<U, V> >
{
public:
    static int bar();
};

template <typename U, typename V>
int Foo<std::pair<U, V> >::bar() { return Foo<U>::bar() + Foo<V>::bar(); }

【讨论】:

  • @litb 据我所知,他的所有功能都是类专业化。我没有看到任何函数模板,是吗?
  • @TimW:当你声明一个类模板时,每个成员函数都是一个独立的函数模板。 OP 正在尝试专门化成员函数模板而不专门化整个类模板。这才是重点。但是,函数模板不支持部分特化。这就是问题所在。
  • @TimW,没有函数模板。但是也没有明确的类模板特化。参见上面的标准引用:这是标准中的一个特例,允许明确地特化类模板的单独非模板成员,而不显式地特化它们的整个类模板。它通过命名给定的隐式实例(在他的示例中,例如Foo&lt;int&gt;Foo&lt;double&gt;)来工作,在没有Foo 的任何部分特化的情况下,它将选择主模板并特化其中的bar 成员。跨度>
  • 我只是假设他是懒惰的,并在示例中留下了类专业化的定义
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-22
相关资源
最近更新 更多