为什么不允许模板特化在不同的命名空间中?

请看我要做什么:

#include <iostream>
namespace first
{
 template <class T>
 class myclass
 { 
  T t;
 public:
  void who_are_you() const
  { std::cout << "first::myclass"; }
 };
}
namespace second
{
 using first::myclass;
 template <>
 class myclass <int>
 {
  int i, j;
 public:
  void who_are_you() const
  { std::cout << "second::myclass"; }
 };
}

这是不允许的.您能否澄清为什么专业化不能位于不同的命名空间中,有哪些可用的解决方案?另外,它是在 C++0x 中修复的吗?

This isn't allowed. Could you please, clarify why can't specializations be in different namespaces, and what are the available solutions? Also, is it something fixed in C++0x?

这将允许我专门化 std::maxstd::swapstd::numeric_limits 等.. 不通过向 ::std::?

This would allow me for example, to specialize std::max, std::swap, std::numeric_limits, etc.. without resorting to undefined behavior by adding something to ::std::?

@AndreyT 以下是我使用它的方式:

@AndreyT Here is how I though I would use it:

// my_integer is a class
std::numeric_limits<my_integer>::max(); // specialized std::numeric_limits for my_integer

这个可以吗?

推荐答案

C++ 2003, §17.4.3.1/1: 程序可以将任何标准库模板的模板特化添加到命名空间 std.这样的特化(完整或部分) 的标准库模板会导致未定义的行为,除非声明依赖于用户定义的外部链接名称,并且除非特化满足原始模板的标准库要求."

C++ 2003, §17.4.3.1/1: "A program may add template specializations for any standard library template to namespace std. Such a specialization (complete or partial) of a standard library template results in undefined behavior unless the declaration depends on a user-defined name of external linkage and unless the specialization meets the standard library requirements for the original template."

因此,您可以专门化一个库模板,并将您的专门化放在命名空间 std 中,只要它依赖于用户定义的类型并满足原始模板的要求.

As such, you're allowed to specialize a library template, and put your specialization in namespace std, as long as it depends on a user defined type and meets the requirements of the original template.

您在已编辑问题中的代码似乎是用户定义名称的特化,该名称(可能)具有外部链接,因此您应该对这部分内容没有任何问题.

The code you have in your edited question seems to be a specialization for a user-defined name that (presumably) has external linkage, so you shouldn't have any problem with that part of things.

只剩下你的专业满足原始模板要求的要求.对于您的类型,其中大部分可能微不足道.我可以看到的唯一可能不明显的部分是您似乎必须为整个模板提供专门化,而不仅仅是 numeric_limits::max().即,您必须执行类似的操作(示例应该在 128 位无符号整数类型的范围内):

That leaves only the requirement that your specialization meet the requirements of the original template. For your type, most of this will probably border on trivial. The only part I can see that might not be obvious is that you do seem to have to provide a specialization for the whole template, not just numeric_limits::max(). I.e., you'll have to do something like (example should be in the ballpark for a 128-bit unsigned integer type):

namespace std { 
template <>
class numeric_limits<my_integer> {
public:

    static const bool is_specialized = true;
    static T min() throw() { return 0;
    static T max() throw() { return /* 2^128-1 */; } // ***
    static const int digits = 128;
    static const int digits10 = 38;
    static const bool is_signed = false;
    static const bool is_integer = true;
    static const bool is_exact = true;
    static const int radix = 2;
    static T epsilon() throw() { return 0; }
    static T round_error() throw() { return 0; }
    static const int min_exponent = 0;
    static const int min_exponent10 = 0;
    static const int max_exponent = 0;
    static const int max_exponent10 = 0;
    static const bool has_infinity = false;
    static const bool has_quiet_NaN = false;
    static const bool has_signaling_NaN = false;
    static const float_denorm_style has_denorm = denorm_absent;
    static const bool has_denorm_loss = false;
    static T infinity() throw() { return 0; }
    static T quiet_NaN() throw() { return 0; }
    static T signaling_NaN() throw() { return 0; }
    static T denorm_min() throw() { return 0; }
    static const bool is_iec559 = false;
    static const bool is_bounded = true;
    static const bool is_modulo = true;
    static const bool traps = false;
    static const bool tinyness_before = false;
    static const float_round_style round_style = round_toward_zero;
};
}

其中相当一部分是针对 FP 类型的,并且不需要对整数类型有意义;我认为它们仍然需要实施.

Quite a few of those are really for FP types, and aren't required to be meaningful for an integer type; I believe they still need to be implemented.

相关文章