Синтаксис для специализации вложенного шаблона
Я пытаюсь выяснить правильный синтаксис для явной специализации вложенного шаблона. Следующий код лучше иллюстрирует:
struct Column_Major;
struct Row_Major;
template<size_t rows, size_t cols, typename T, typename Allocator>
class Matrix
{
/* bunch of members */
template <typename storage = Column_Major>
class Iterator
{
/* bunch of members */
};
};
Я хотел бы написать явную специализацию для template <> class Matrix<...>::Iterator<Row_Major
, но синтаксис ускользает от меня. У меня есть подозрение, что нельзя явно специализировать класс Iterator без явной специализации содержащего класса Matrix. Но я был бы очень рад, если есть способ сделать это.
Я знаю, что я мог бы сделать класс Iterator отдельным классом, а не членом класса Matrix, но наличие вложенных в него классов позволяет мне получить полный доступ к параметрам шаблона и datamebers класса Matrix, что упрощает работу. Я знаю, что могу обойти это, если нужно, но сначала хотел бы изучить и понять возможности для вложенного подхода.
Спасибо,
Шмуэль
Ответы
Ответ 1
Для явной специализации вам нужно специализировать внешний класс перед внутренним, вы можете увидеть этот вопрос, например.
Существует обходное решение, использующее частичную специализацию:
template<size_t rows, size_t cols, typename T, typename Allocator>
class Matrix
{
// Notice the additionnal dummy parameter
// vvvvvvvvvvvvv
template <typename storage = Column_Major, bool = true>
class Iterator
{
};
// Specialization
template <bool dummy>
class Iterator<Row_Major, dummy>
{
};
};
Ответ 2
Вы можете сделать ответ Synxis (использование параметра фиктивного дефиниции) еще более чистым с С++ 11:
/// template <typename X>, not needed for the example
struct Outer
{
private:
template <typename A, typename D = void>
struct Inner
{
Inner() { cout << "default" << endl; }
};
template <typename D>
struct Inner<int,D>
{
Inner() { cout << "int" << endl; }
};
public:
template <typename T>
using Nested = Inner<T>;
};
Преимущество этого улучшения заключается в том, что подпись Nested имеет только один параметр шаблона, который, я думаю, поможет, если вы хотите правильно его сопоставить в метапрограмме шаблона.
Ответ 3
Я удивлен, что параметр шаблона для вложенного класса не является параметром родительского класса.
Вложенный класс может использовать параметры шаблона родителя, и это более тесно связывает вложенный класс с родителем. Ваше использование итератора слова предполагает, что это хорошо, итератор, безусловно, выполняет итерацию по тому же типу, который содержит родительский элемент?
Я бы сделал это вот так:
template <class T>
class Outer
{
public:
class Inner
{
void Fn( T in )
{
}
};
};
// specialisation
void Outer<double>::Inner::Fn( double in )
{
}