[cpp]请问gcc 3.x下的一个模板问题

Wu Yongwei adah at sh163.net
Wed May 3 18:05:38 CST 2006


昨天晚上没有在编译器上充分测试,今天测试了一下,结果还有点令我惊讶。目前
我无法写出在 MSVC8 和 GCC 下都能正常工作的代码!你原先的写法在 MSVC8 下
(以及最新版本的 Digital Mars C++ 编译器)能工作,在 GCC 下能通过的写法是:

头文件中:

template <typename DataType>
class FMC
{
    ...
};

template <>
const double FMC<double>::Epsilon;

某一个 .cpp 文件中:

包含头文件
template <>
const double FMC<double>::Epsilon = static_cast<double>(0.0000000001);

其它 .cpp 文件中只需包含头文件即可。即特化在头文件中需要声明,但不应定义。

MSVC6 下我没找到一种写法可以在所有情况下正常工作。

个人倾向于 GCC 是正确的。但是&# 8230;&# 8230;我不能百分百确认。我想到
comp.lang.std.c++ 上去问一下,如果有结果,再告诉你。

关于宏的可变参数问题,如果你想寻找 GCC 的解决方案的话,google 一下&# 8220;gcc
macro __VA_ARGS__&# 8221;。我不知道任何跨平台的解决方案。

吴咏炜

rockie wrote:
> 吴咏炜,你是对的,已经在gcc 3.x下过了,非常感谢。
> 还有一个问题,也是郁闷了很久的,关于宏的参数问题。
> 即如何让一个宏支持参数数目可变的参数,如函数的...参数
> #ifdef ENABLE_LOG 	
> 
> #include "logger.h"	
> enum ChannelTag
> {
> 	CT_NONE = 0,
>     CT_ERROR,
> 	CT_PARSE,
>     CT_SEND,
>     CT_SENSE,
>     CT_NOTIFY,
> 	//...      
> 	CT_MAX // append channel tags before this line
> };	
> 
> extern Logger LOGGER; //Logger是个容器,重载了->操作符
> #define DoLog LOGGER->Log	
> //Log方法声明:
> //void Log(IndexType channel, const char* szFmt, ...);
> //使用例子:DoLog(CT_MEASURE, "FLAG1 not seen.");
> 
> //#define AssertLog(x, y, z) if(!(x)){DoLog(y,z)} //这个是不行的,不能支持多参数
> //要问的问题:
> //如何定义一个宏使得可以实现如下功能?即
> //AssertLog(断言条件, CT_MEASURE, "FLAG1 not seen.");
> //并可支持可变数目的参数
> //AssertLog(断言条件, CT_PARSE, "Unknown vision sensation at time[%f]: [%s]", time, sense);
> 
> #else //NOT ENABLE_LOG
> 
> #ifdef _WIN32
> 	#define DoLog(x) NULL		
>    // #define AssertLog(x) NULL
> #else
> 	#define DoLog(...) NULL		
>    // #define AssertLog(...) NULL
> #endif //
> 
> #pragma warning(disable: 4002)
> 
> #endif //ENABLE_LOG
> 
> ------------------				 
> rockie
> 2006-05-03
> 
> -------------------------------------------------------------
> 发件人:Wu Yongwei
> 发送日期:2006-05-03 00:24:43
> 收件人:C++ Discuss Group
> 抄送:
> 主题:Re: [cpp]请问gcc 3.x下的一个模板问题
> 
> rockie wrote:
> 
>>大家好, 有个问题难住了。
>>以下程序打开注释在vc6, vs05下可以通过编译,不知道为什么在gcc 3.x下编译不通过。
>>谢谢指教。
>>
>>template <typename DataType>
>>class FMC
>>{
>>public:
>>	...
>>    static const DataType Epsilon;
>>    ...
>>private:
>>    FMC() {}
>>};
>>
>>/*
>>template <> 
>>const float FMC<float>::Epsilon = static_cast<float>(0.000001); 
>>
>>template <> 
>>const double FMC<double>::Epsilon = static_cast<double>(0.0000000001); 
>>*/
>>
>>template <typename DataType> 
>>const DataType FMC<DataType>::Epsilon = static_cast<DataType>(0.000001); 
>>
>>错误提示是multiple definition
>> 				
>>--------------
>>rockie
>>rockie at student.dlut.edu.cn
>>2006-05-02
> 
> 
> 我估计你出问题的原因是把被注释掉的代码放到了头文件中,并在多处包含了该头
> 文件。解决方法是把这些代码移到(只编译、连接一次的)一个 .cpp 文件中。
> 
> 我认为 GCC 的做法是符合 C++ 标准的。C++1998 标准的 14.7.3.15 这么写的:
> 
> An explicit specialization of a static data member of a template is a
> definition if the declaration includes an initializer; otherwise, it is
> a declaration. [Note: there is no syntax for the definition of a static
> data member of a template that requires default initialization.
> 
>     template<> X Q<int>::x;
> 
> This is a declaration regardless of whether X can be default initialized
> (8.5). ]
> 
> 也就是说,被注释掉的这两段代码被视作定义而不是声明。在头文件定义类成员变
> 量当然是要出问题的。错误 multiple definition 也就正常了。
> 
> 吴咏炜


More information about the Cpp mailing list