总模板专业化

时间:2010-10-13 22:16:01

标签: c++

我正在阅读Meyers关于有效c ++编程的书,在第25项我发现total template specialization,但我无法理解,这是什么意思?他还举了一个例子:

namespace std {

    template<>
    void swap<Widget>(Widget& a, Widget& b)
      {
          swap(a.pimpl, b.pimpl);
      }

    }

这句话是什么意思:template<>(为什么没有typename?)

提前致谢

2 个答案:

答案 0 :(得分:13)

通常,您使用模板是因为您有一段足够通用的代码,可以应用于不同类型。但是,对于某些类型,您可能希望做一些不同的事情(例如,因为有一种更有效的方法)。这是模板专业化拯救时(您可以将它们视为“特殊情况”模板):

例如:

class Foo {};
class Bar {};

// Primary template - the most generic.
template<typename T, typename U>
class MyClass
{
public:
    void DoSomething()
    {
        /* Performs the same generic operation for all T and U... */
    }
};

// Total specialization of the primary template
template<>
class MyClass<Foo, Bar>
{
public:
    void DoSomething()
    {
        /* ...Except when T is Foo and U is Bar.
              We may possibly do something different
              to allow for higher efficiency. */
    }
};

int main()
{
    MyClass<int, char> a; // Uses the generic version of MyClass
    MyClass<Foo, Bar> b;  // Uses the (total) template specialization
}

请注意,我在这里使用的是类,但概念是相同的。您可以看到类似的语法适用于函数模板。

但是,对于类,当没有在模板专门化中完全指定所有参数时,存在部分模板特化这样的事情。它可能看起来像这样:

// Partial specialization #1
template<typename U>
class MyClass<Foo, U>
{
public:
    void DoSomething()
    {
        /* ...Do something special when T is Foo.
              This code doesn't care what type U is. */
    }
};

template<typename T> class Baz {};

// Partial specialization #2
template<typename Z>
class MyClass<Foo, Baz<Z> >
{
public:
    void DoSomething()
    {
        /* ...Do something special when T is Foo, and U is Baz.
              This code doesn't care what Baz gets for its
              template parameter. */
    }
};

int main()
{
    MyClass<int, char> a;      // Uses the generic version of MyClass
    MyClass<Foo, char> b;      // Uses partial template specialization #1
    MyClass<Foo, Baz<int> > c; // Uses partial template specialization #2
    MyClass<Foo, Bar> d;       // Uses the total template specialization
}

请注意,处理这些特化时没有歧义,因为编译器会选择最适合模板参数的特殊化。通过允许这些“特殊情况”模板,我们可以创建真正通用的库。

另请注意,此部分专业化业务仅适用于类,而不适用于函数! (您不能部分专门化功能模板)。这就是为什么你的代码片段按原样编写的原因 - 你只能完全专门化函数模板 - 其他任何东西都是std命名空间中的函数重载(C ++标准不允许)。我花时间提到这一点,因为很多人似乎都错了。

namespace std
{
    /* Do **not** do this in the std namespace!!!
       You're not actually partially specializing the function,
       you're overloading the function in the std namespace
       which is prohibited by the C++ standard. */
    template<typename T>        
    void swap<Widget<T> >(Widget<T>& a, Widget<T>& b) {}
}

答案 1 :(得分:1)

它定义了swap<T>T的情况下函数Widget的实现。这是“全部”专业化,因为它为所有指定swap<T>的模板参数的类型(在此示例中只有一个)。

如果swap<Widget>的实施需要执行与通用swap<T>代码不同的操作,则执行此操作。

template<>部分告诉编译器您正在提供模板的特化。 <>之间没有任何内容,因为没有要指定的模板参数 - swap<Widget>部分定义了所有参数。