3

Very interesting piece of code here. I have created it with the only purpose - to demonstrate the behaviour of the xlC compiler.

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;
}

If you compile this code as it is, it's causing a compilation error:

!$ 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

And now, if we uncomment the line started with the "//namespace" (which is nothing else but template specialization for the typename D1< int>, compiler error disappears.

Gnu compiler seems to have no problem with it. Does any of you have an idea?

PS. The problem was found of course in a real project and this is just a simplified example. In real project, there are hundreds of classes like D1< int>. They suppose to work out of the box. But for xlC I have to write the specialized functions for each particular case. That hurts a lot ...

novak Li
  • 223
  • 4
  • 12

2 Answers2

1

xlC definitely behaves differently than gcc for templates. I've had similar issues on a project at work.

Try to add the definition of the A1 constructor. It's missing.
It's very probable that xlC requires it at compilation time, while gcc would require it only at link time. See GCC log.

Yohan Danvin
  • 885
  • 6
  • 13
  • My fault, you're right. And no, it doesn't help. The problem comes from the real project on which I spent a few hours to understand it and finally came up with this simplified code snippet that leads to the same compilation error. The thing I can't understand - why D1< int> is not defined for compiler in one case and is defined in second case when you simply enable a specialized function? That function in my opinion is just an overhead, cuz f() is doing the same for every type by default. Doesn't it look like a compiler bug for you? – novak Li Jun 24 '13 at 07:56
  • Yes it does. Can you update your question with the 'simplified code snippet' you're talking about? I still can't see the A1 constructor definition. I'll try to compile it on my side with xlC too. – Yohan Danvin Jun 24 '13 at 09:11
1

Its definitely a compiler bug, the default argument for class A1 public: A1( const T& arg = ns::f<T>() );

Is causing a request for implicit instantiation D1<int> at line 7 (before class D1 is defined)

The request should not have been made at line 7 (the compiler's bug).

A simpler workaround is to place an explicit instantiation of D1<int> right after the definition of D1

template class D1<int>;

Another workaround is to avoid using the default argument causing the incorrect implicit instantiation by initializing the data member in the ctor of my

my::my() : a(ns::f< D1<int> > ()) { };

I can get this fixed in the next release, but to get a fix in V12.1 you would need to open a defect with service.

valiano
  • 16,433
  • 7
  • 64
  • 79