Посмотрите то, что я пытаюсь сделать:
#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?
Это позволило бы мне, например, для специализации 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
Это может быть сделано?
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;
};
}
Довольно многие из них действительно предназначены для FP-типов и не обязаны быть значимыми для целого типа; я считаю, что их все равно нужно реализовать.
Почему вообще возник такой вопрос? Не понимая этого, трудно даже начать отвечать на него.
Специализация изменяет основной шаблон. Она никак не "отделяется" от основного шаблона. В определенном смысле, как концепция высокого уровня, это все тот же шаблон (даже если на более низком уровне он определяется как независимый). Поэтому, по очевидным причинам, он находится в том же пространстве имен, что и основной шаблон.
Извините, я просто не могу дать лучшего объяснения, поскольку не понимаю, как может возникнуть такой вопрос.
BTW, что вы имеете в виду под "в другом пространстве имен"? Вы хотите, чтобы специализация была членом другого пространства имен? Или вы хотите, чтобы специализация была определена в другом пространстве имен в исходном коде, но оставалась членом исходного пространства имен?
.Это все усложняет:
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
}
Я понимаю ваше разочарование, я часто желал того же.Это кажется определенно возможным, и я, конечно, не верю аргументу логической группировки, однако должен признать, что это потребует еще больше усилий от авторов компилятора, а правильный синтаксический анализ C ++ уже достаточно сложен в его нынешнем виде.
Шаблоны в C ++ немного беспорядочные, если вы хотите мое мнение, но тогда это легко сказать, имея опыт и после 20 лет использования :)