Очень интересный кусок кода здесь. Я создал его с единственной целью — продемонстрировать поведение компилятора xlC.
namespace ns {
template<typename T> inline T f() { return T(); }
template<> inline double f<double>() { return 0.001; } // test specialization
};
template<typename T >
class A1 {
public: A1( const T& arg = ns::f<T>() ) {};
};
template<typename T>
class D1 {
public: D1(T t = 0) : t_(t) {};
private: T t_;
};
class my {
A1< D1<int> > a;
public: my() ;
};
//namespace ns { template<> D1<int> f<D1<int> >() { return D1<int>(); } }
my::my() { };
void ff() {
my m;
A1<double> ad;
}
Если вы скомпилируете этот код как есть, это вызовет ошибку компиляции:
!$ xlC -c b.cpp
"b.cpp", line 7.40: 1540-0253 (S) This use of undefined class "D1<int>" is not valid.
"b.cpp", line 22.10: 1540-1205 (I) The error occurred while converting to parameter 1 of "A1<D1<int> >::A1(const D1<int> &)".
!$ xlC -qversion
IBM XL C/C++ for AIX, V12.1 (5765-J02, 5725-C72)
!$ uname -a
AIX build25 1 6 00C8B3424C00 powerpc AIX
А теперь, если мы раскомментируем строку, начинающуюся с «// namespace» (которое является ничем иным, как специализацией шаблона для typename D1< int>, ошибка компилятора исчезает.
Компилятор GNU, похоже, не имеет проблем с этим. У кого-нибудь из вас есть идея?
PS. Конечно, проблема была обнаружена в реальном проекте, и это только упрощенный пример. В реальном проекте есть сотни классов, таких как D1< Int>. Они предполагают работать из коробки. Но для xlC я должен написать специализированные функции для каждого конкретного случая. Это очень больно …
xlC определенно ведет себя иначе, чем gcc для шаблонов. У меня были похожие проблемы с проектом на работе.
Попробуйте добавить определение конструктора A1. Это отсутствует.
Весьма вероятно, что xlC требует этого во время компиляции, в то время как gcc потребует этого только во время компиляции.
Увидеть Журнал GCC.
Это определенно ошибка компилятора, аргумент по умолчанию для класса A1
public: A1( const T& arg = ns::f<T>() );
Вызывает запрос на неявную реализацию D1<int>
в строке 7 (до определения класса D1)
Запрос не должен был быть сделан в строке 7 (ошибка компилятора).
Более простой обходной путь состоит в том, чтобы поместить явную реализацию D1<int>
сразу после
определение D1
template class D1<int>;
Другой обходной путь — избегать использования аргумента по умолчанию, вызывающего неправильное неявное создание экземпляра, путем инициализации члена данных в ctor моего
my::my() : a(ns::f< D1<int> > ()) { };
Я могу исправить это в следующем выпуске, но для исправления в V12.1 вам нужно будет открыть дефект в сервисе.