3

这里有一段非常有趣的代码。我创建它的唯一目的是演示 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

现在,如果我们取消注释以“//命名空间”开头的行(这只是类型名 D1<int> 的模板特化,编译器错误就会消失。

Gnu编译器似乎没有问题。你们有什么想法吗?

PS。这个问题当然是在一个真实的项目中发现的,这只是一个简化的例子。在实际项目中,像 D1<int> 这样的类有数百个。他们认为开箱即用。但是对于 xlC,我必须为每个特定情况编写专门的函数。那很伤...

4

2 回答 2

1

对于模板,xlC 的行为肯定与 gcc 不同。我在工作中的一个项目中遇到过类似的问题。

尝试添加 A1 构造函数的定义。它不见了。
xlC 很可能在编译时需要它,而 gcc 只在链接时需要它。请参阅GCC 日志

于 2013-06-23T12:09:29.140 回答
1

它绝对是一个编译器错误,A1 类的默认参数 public: A1( const T& arg = ns::f<T>() );

在第 7 行引起对隐式实例化的请求D1<int>(在定义类 D1 之前)

该请求不应该在第 7 行(编译器的错误)提出。

D1<int>一个更简单的解决方法是在 D1 的定义之后放置一个显式实例化

template class D1<int>;

另一种解决方法是通过初始化 my 的 ctor 中的数据成员来避免使用导致不正确的隐式实例化的默认参数

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

我可以在下一个版本中修复此问题,但要在 V12.1 中修复,您需要使用服务打开一个缺陷。

于 2013-06-24T13:45:56.473 回答