2013-06-23 4 views
3

Очень интересный фрагмент кода здесь. Я создал его с единственной целью - продемонстрировать поведение компилятора xlC.Ошибка компилятора C++ и IBM?

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 

И теперь, если мы раскомментировать линия началась с «// пространство имен» (который есть не что иное но специализация шаблона для TYPENAME D1 < INT>, ошибка компилятора исчезает.

Gnu компилятор, кажется, нет никаких проблем с этим. есть ли у кого из вас есть идея?

PS. Конечно, проблема была найдена в реальном проекте, и это просто упрощенный пример. В реальном проекте есть сотни классов, таких как D1 < int>. Они полагают, что они работают из коробки. Но для xlC мне приходится писать специализированные функции для каждого частного случая. Это очень больно ...

ответ

1

xlC определенно ведет себя иначе, чем gcc для шаблонов. У меня были схожие проблемы с проектом на работе.

Попробуйте добавить определение конструктора A1. Он отсутствует.
Очень вероятно, что xlC требует его во время компиляции, тогда как gcc потребует его только во время соединения. См. GCC log.

+0

Моя вина, вы правы. И нет, это не помогает. Проблема возникает из реального проекта, на котором я потратил несколько часов, чтобы понять его, и, наконец, придумал этот упрощенный фрагмент кода, который приводит к той же ошибке компиляции. То, что я не могу понять - почему D1 < int> не определен для компилятора в одном случае и определяется во втором случае, когда вы просто включаете специализированную функцию? Эта функция, на мой взгляд, просто накладная, cuz f() делает то же самое для каждого типа по умолчанию. Разве это не похоже на ошибку компилятора для вас? –

+0

Да, да. Можете ли вы обновить свой вопрос с помощью «упрощенного фрагмента кода», о котором вы говорите? Я все еще не вижу определения конструктора A1. Я попытаюсь скомпилировать его на моей стороне с помощью xlC. –

1

Его определенно ошибка компилятора, аргумент по умолчанию для класса A1 public: A1 (const T & arg = ns :: f());

вызывает запрос на неявный экземпляр D1 в строке 7 (до класса D1 определен)

Запрос не должен был быть сделан в строке 7 (ошибка компилятора).

Более простой обходной путь заключается в размещении явного экземпляра D1 сразу после определения D1

шаблон класса D1;

Другого обходной путь, чтобы избежать использования аргумента по умолчанию вызывает неправильный неявный экземпляр инициализации элемента данных в CTOR моего

моих :: моего(): а (Ns :: ф < D1>()) {};

Я могу исправить это в следующей версии, но для исправления в V12.1 вам нужно будет открыть дефект с сервисом.

+0

Думаете, вы имеете в виду «шаблонный класс D1 ;» потому что «шаблонный класс D1;» не является экземпляром шаблона. –

+0

да, это опечатка –