Поскольку люди, похоже, обращаются к этому вопросу, когда речь заходит об ошибках компоновщика, я собираюсь добавить это здесь.
Одной из возможных причин ошибок компоновщика с GCC 5.2.0 является то, что новая библиотека libstdc ++ ABI теперь выбран по умолчанию.
Если вы получаете ошибки компоновщика о неопределенных ссылках на символы, которые включают типы в пространстве имен std :: __ cxx11 или теге [abi: cxx11], то это, вероятно, указывает на то, что вы пытаетесь связать файлы объектов, которые были скомпилированы с различными значениями для макроса _GLIBCXX_USE_CXX11_ABI. Это обычно происходит при подключении к сторонней библиотеке, которая была скомпилирована с более старой версией GCC. Если сторонняя библиотека не может быть перестроена с новым ABI, вам нужно будет перекомпилировать свой код со старым ABI.
blockquote>. Если вы вдруг получите ошибки компоновщика при переключении на GCC после 5.1.0 это было бы замечательно.
Для явной специализации вам нужно специализировать внешний класс перед внутренним, вы можете увидеть этот вопрос, например .
Существует обходное решение, использующее частичную специализацию:
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>
{
};
};
Я удивлен, что параметр шаблона для вложенного класса не является параметром родительского класса.
Вложенный класс может использовать параметры шаблона родителя, и это более тесно связывает вложенные класс для родителя. Ваше использование итератора слова предполагает, что это хорошо, итератор, конечно, итерации по тому же типу, который содержит родительский элемент.
Я бы сделал это следующим образом:
template <class T>
class Outer
{
public:
class Inner
{
void Fn( T in )
{
}
};
};
// specialisation
void Outer<double>::Inner::Fn( double in )
{
}
Вы можете сделать ответ Synxis (использование параметра фиктивного значения по умолчанию) еще более чистым с C ++ 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 имеет только один параметр шаблона , который, я думаю, поможет, если вы хотите правильно его сопоставить в мета-программировании шаблона.