Ошибка компилятора С++ и IBM?

Здесь очень интересный фрагмент кода. Я создал его с единственной целью — продемонстрировать поведение компилятора 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" (что не что иное, как специализация шаблона для имени типа D1‹ int>), ошибка компилятора исчезнет.

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

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


person novak Li    schedule 23.06.2013    source источник


Ответы (2)


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

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

person Yohan Danvin    schedule 23.06.2013
comment
Моя вина, ты прав. И нет, не помогает. Проблема связана с реальным проектом, над которым я потратил несколько часов, чтобы понять его, и, наконец, придумал этот упрощенный фрагмент кода, который приводит к той же ошибке компиляции. Не могу понять - почему D1‹ int› не определяется для компилятора в одном случае, а определяется во втором случае, когда вы просто включаете специализированную функцию? Эта функция, на мой взгляд, просто накладная, потому что f() по умолчанию делает то же самое для каждого типа. Разве это не похоже на ошибку компилятора для вас? - person novak Li; 24.06.2013
comment
Да, это так. Можете ли вы обновить свой вопрос с помощью «упрощенного фрагмента кода», о котором вы говорите? Я все еще не вижу определения конструктора A1. Я тоже попробую скомпилировать на своей стороне с помощью xlC. - person Yohan Danvin; 24.06.2013

Это определенно ошибка компилятора, аргумент по умолчанию для класса 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, вам нужно будет открыть дефект с помощью службы.

person Catherine Morton    schedule 24.06.2013
comment
Думаю, вы имеете в виду класс шаблона D1‹int›; потому что класс шаблона D1; не является экземпляром шаблона. - person Yohan Danvin; 26.06.2013