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 ...
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With