开发者

What is the proper way to declare a specialization of a template for another template type?

The usual definition for a specialization of a template function is something like this:

class Foo {
    [...]
};

namespace std {
    template<>
    void swap(Foo& left, Foo& right) {
        [...]
    }
} // namespace std

But how do you properly define the specialization when the type it's specialized on is itself a template? Here's what I've got:

template <size_t Bits>
class开发者_如何学C fixed {
    [...]
};

namespace std {
    template<size_t Bits>
    void swap(fixed<Bits>& left, fixed<Bits>& right) {
        [...]
    }
} // namespace std

Is this the right way to declare swap? It's supposed to be a specialization of the template function std::swap, but I can't tell whether the compiler is seeing it as such, or whether it thinks that it's an overload of it or something.


Your solution isn't a template specialization, but an overload of a function in the std namespace, which is "undefined behavior" per the c++ standard.

This question is exactly your question.

Scott Meyers discusses this in Effective C++, and there is a followup thread on usenet's comp.lang.c++.

  • He suggests that you define it in fixed's own namespace.
  • Make sure 'fixed' is in a namespace.
  • Don't prefix calls to swap with 'std::'.
  • Let Koenig (a.k.a. argument dependent) lookup find the right swap function.

If you're seeing compilation errors when trying to define this in namespace std, it's likely due to your unfortunate choice of class names :) When within namespace std "fixed" is being seen as std::fixed, the floating point precision operator.


Partial specializations of function templates are not allowed, so the template for fixed<Bits> declares a new overload, not a specialization.

This doesn't matter, though, since a call like std::swap(a, b) will just choose the best matching function. It doesn't require that the function is a specialization of the generic std::swap template. If the best matching function is a overload instead of a specialization, the overload will be called.


Syntactically your "specialization" is done correctly. However, as others already noted, it is not really a partial specialization but a function overload. Function templates don't support partial specialization.

It is worth noting though that adding anything to namespace std is prohibited by the language specification (see 17.4.3.1/1). I understand why you insisted on doing it in std specifically, since you were trying to partially specialize std::swap. Since your swap is really an overload and not a specialization, you can safely do it outside std, within the same namespace that contains yor fixed. Argument-dependent name lookup ("Koenig lookup") should make sure that your swap is found by name lookup when applied to arguments of type fixed (unless the calling code explicitly refers to std::swap instead of just swap).


A template parameter cannot be declared with a value that is not determined until run-time. To use numbers for a template parameter, it needs to be a 'const' so it can be resolved at compile-time:

template <const size_t Bits> 
class fixed { 
    [...] 
}; 

namespace std { 
    template<const size_t Bits> 
    void swap(fixed<Bits>& left, fixed<Bits>& right) { 
        [...] 
    } 
} // namespace std 
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜