[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