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

Ara*_*raK 12 c++ templates namespaces template-specialization

请看看我想做什么:

#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"; }
 };
}
Run Code Online (Sandbox Code Playgroud)

这是不允许的.请问,请说明为什么专业化不能在不同的命名空间中,以及有哪些可用的解决方案?此外,它是在C++ 0x中修复的东西吗?

这将让我举例来说,专注std::max,std::swap,std::numeric_limits,等.不加东西诉诸未定义行为::std::


@AndreyT这是我如何使用它:

// my_integer is a class
std::numeric_limits<my_integer>::max(); // specialized std::numeric_limits for my_integer
Run Code Online (Sandbox Code Playgroud)

可以这样做吗?

Jer*_*fin 7

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

因此,你被允许专门库模板,把你的专业化的命名空间std,只要它依赖于用户定义类型,满足了原始模板的要求.

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

只留下您的专业化要求符合原始模板要求的要求.对于你的类型,大多数这可能是微不足道的.我可以看到的唯一可能不明显的部分是你似乎必须为整个模板提供专业化,而不仅仅是numeric_limits::max().即,你必须做类似的事情(例如,应该在128位无符号整数类型的球场):

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;
};
}
Run Code Online (Sandbox Code Playgroud)

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

  • 否 - "外部链接"通常意味着它不是"静态"或匿名命名空间. (2认同)

Mat*_* M. 5

它使事情复杂化:

namespace first
{
  template <class T> class TArray;
}

namespace second
{
  using first::TArray;

  template <class U> class TArray < Node<U> >;
  //                              ^
  // Only there do you realize it's a specialization and not another template
}
Run Code Online (Sandbox Code Playgroud)

我理解你的沮丧,我经常希望同样的事情。这似乎绝对有可能,我当然不会购买逻辑分组参数,但是我必须承认,这需要编译器编写者付出更多的努力,而且正确解析 C++ 就目前而言已经足够困难了。

如果您想听听我的意见,C++ 中的模板有点混乱,但是凭借经验和使用 20 年之后,很容易说出来:)