没见过这种编译警告信息,求教!

tangshuiling 2009-05-04 09:11:50

代码简单描述如下:
template <bool> struct compiletime;
template<> struct compiletime<true>
{
compiletime(...) {}
};
template <> struct compiletime<false> {};
struct ERROR{};

compiletime<sizeof(char)>=sizeof(int)>(ERROR()); //测试代码出现编译警告

warning C4930: 'compiletime<false> ERROR(void)': prototyped function not called
(was a variable definition intended?)
ERROR(void)函数没有被调用是何意?并且被编译器调侃为故意作为局部变量
...全文
456 36 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
36 条回复
切换为时间正序
请发表友善的回复…
发表回复
yshuise 2009-05-05
  • 打赏
  • 举报
回复
int();
int(6);

这些都没有警告。类型加一个括弧就是对象。至所以出现上面的问题,还是编译器的局限性。
yeungqi 2009-05-05
  • 打赏
  • 举报
回复
up
Jinhao 2009-05-05
  • 打赏
  • 举报
回复
(compiletime<sizeof(char)>=sizeof(int)>(ERROR()));
加一个括号,就不是声明了。
Jinhao 2009-05-05
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 Jinhao 的回复:]
compiletime <sizeof(char)>=sizeof(int)>(ERROR());

这也不是函数声明.

只是一个函数原型.
typedef compiletime <sizeof(char)>=sizeof(int)> return_type;
return_type(ERROR());

意思就是返回一个compiletime <sizeof(char)>=sizeof(int)> 对象的,参数为 返回一个ERROR对象的无参数的函数指针 的函数

所以,那个警告提醒的恰到好处.告诉你那不是在调用一个函数
[/Quote]

本人不才,思考错误.
compiletime <sizeof(char)>=sizeof(int)>(ERROR());

5楼解释正确。
compiletime <sizeof(char)>=sizeof(int)>(ERROR());
就是
compiletime <sizeof(char)>=sizeof(int)> ERROR();

警告已经说出来了。
放置在ERROR()外的那对括号,并不是指定这样的形式 (参数,参数...)。

在类型声明中。
Type Declarator
比如
int i;
如果是函数生命,Declarator的形式必须是
D(参数, 参数...)

对于ERROR()可以解释成函数类型,返回ERROR的无参数函数。

但是在整个类型声明中,还能接受一种形式。
Type (Declarator)
例如
int (i);

那么void foo(); 写成void (foo()); 也是合法的。
因此,compiletime <sizeof(char)>=sizeof(int)>(ERROR());
首先用Type (Declarator)这种形式匹配了。
而不是被解释成
返回一个compiletime <sizeof(char)>=sizeof(int)> 对象的,参数为 返回一个ERROR对象的无参数的函数指针 的函数。
yshuise 2009-05-05
  • 打赏
  • 举报
回复
修改过后,下面这个版本可以无警告编译通过:
template <bool> 
struct compiletime;

template<>
struct compiletime<true>
{
compiletime(...) {}
};
struct ERROR{};

template <>
struct compiletime<false>{
compiletime(ERROR ) {}
};




int _tmain(int argc, _TCHAR* argv[])
{

compiletime<sizeof(char)>=sizeof(int)>::compiletime(ERROR());

return 0;

}
yshuise 2009-05-05
  • 打赏
  • 举报
回复
不是函数声明,而是创建一个临时对象。
compiletime<sizeof(char)>=sizeof(int)>(ERROR());
sizeof(char)>=sizeof(int) 显然为false
compiletime<false>(ERROR());行吗?
显然不对,因为没有这么一个构造函数,参数是ERROR(),这个匹配的是compiletime<true>(ERROR());
fallening 2009-05-05
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 Jinhao 的回复:]
compiletime <sizeof(char)>=sizeof(int)>(ERROR());

这也不是函数声明.

只是一个函数原型.
typedef compiletime <sizeof(char)>=sizeof(int)> return_type;
return_type(ERROR());

意思就是返回一个compiletime <sizeof(char)>=sizeof(int)> 对象的,参数为 返回一个ERROR对象的无参数的函数指针 的函数

所以,那个警告提醒的恰到好处.告诉你那不是在调用一个函数
[/Quote]
up
hjjdebug 2009-05-05
  • 打赏
  • 举报
回复
to jinhao:
我也装了vs2005, 无奈启动太慢。虽然它的界面等可能更好。既然老大推荐,碰到大项目可以考虑vs2005.
谢谢!
Jinhao 2009-05-05
  • 打赏
  • 举报
回复
[Quote=引用 34 楼 hejinjing_tom_com 的回复:]
to: taodm
兴趣是有,不过没时间研究语言,但可以花一点时间研究一下编译器。因为县官不如现管。
有时候觉得它不尽合理,但也只能屈从于编译器了。因为我们还要用它。
所以我通常止于编译器,而且我现在通常用vc6,因为它短小,精悍。至于它的违法,bug,还能忍受。
[/Quote]

无语。你写木马?要这么小做什么?我们已经有很多代码在VC6上已经不能编译了,最低的要求也就是7.1
hjjdebug 2009-05-05
  • 打赏
  • 举报
回复
to: taodm
兴趣是有,不过没时间研究语言,但可以花一点时间研究一下编译器。因为县官不如现管。
有时候觉得它不尽合理,但也只能屈从于编译器了。因为我们还要用它。
所以我通常止于编译器,而且我现在通常用vc6,因为它短小,精悍。至于它的违法,bug,还能忍受。
Jinhao 2009-05-05
  • 打赏
  • 举报
回复
[Quote=引用 31 楼 hejinjing_tom_com 的回复:]
int a(int ()); 为什么编译器要解释成函数声明 ?
如果这样定义 int i= int(), 则 i=0;
所以 int a(int()); 编译器也完全有理由理解为 声明一个变量a, 用0 初始化变量a.
可是它选择了前者,这里有什么编译的优先选项吗?
[/Quote]

这不是编译器想当然的认为谁优先就优先觉得它是什么,这是C++语言的一部分。不是由编译器来实现语言,而是由语言来约束编译器。当然有的编译器厂商觉得语言的某些部分不是他想遵循的,那也是在没有标准之前的事了,例如VC6。

int a(int ()); //这也是语言明确了的,因此编译器也遵循这个规则。
这里也是声明,关键是看到底声明了一个什么。例如。
int b;
int c(int(b)); //声明函数,返回值int,参数int
c也出乎于的意料。具体看19楼的解释。

int i= int(); //这是大家推荐的写法,避免了那种模棱两可的形式。
taodm 2009-05-05
  • 打赏
  • 举报
回复
楼上的,感兴趣就找本<C++ Gotchas>看看吧。
确实存在着一些优先原则。
hjjdebug 2009-05-05
  • 打赏
  • 举报
回复
[Quote=引用 23 楼 Jinhao 的回复:]
这些都是明确的,对于警告,不是所有的情况都会报。
int(); 创建一个临时对象
int(6); 创建一个临时对象,初值为6

两个都是在调用构造函数

int a(); //声明函数
int b(6); //用6初始化b

int a(int()); //声明函数,返回值int,参数int(*)()
int b(int(6)); //用6初始化b,b是一个int
int c(int(b)); //声明函数,返回值int,参数int
[/Quote]
int a(int ()); 为什么编译器要解释成函数声明 ?
如果这样定义 int i= int(), 则 i=0;
所以 int a(int()); 编译器也完全有理由理解为 声明一个变量a, 用0 初始化变量a.
可是它选择了前者,这里有什么编译的优先选项吗?
Jinhao 2009-05-05
  • 打赏
  • 举报
回复
[Quote=引用 29 楼 tangshuiling 的回复:]
像模板这种不具备良好移植性的代码
[/Quote]

这不是模板的问题,而是编译器的问题。选用新的编译器,再说,现在编译器开发商大都支持标准了。不支持标准的编译器谁还用呢
tangshuiling 2009-05-05
  • 打赏
  • 举报
回复

谢谢荣哥、Jinhao、 yshuise 以及道兄,每次我发贴的问题荣哥都不遗余力地给予帮助真是非常的感谢,确实
此类代码在实际的工作中凤毛麟角,不但生涩而且难懂,考验编译器的能力本身就是编码工作中的不幸,更何况
像模板这种不具备良好移植性的代码尤其如此。
受教了,再次感谢!!!
Jinhao 2009-05-05
  • 打赏
  • 举报
回复
[Quote=引用 27 楼 yshuise 的回复:]
我觉得你这个推论不对。
[/Quote]

呵呵,这不是推论。比如同样的形式int(ERROR()); VC就不会给你警告

函数声明是需要返回类型,函数名,函数参数

compiletime <sizeof(char)>=sizeof(int)>(ERROR());
全部都有了。
返回类型compiletime <sizeof(char)>=sizeof(int)>
函数名 ERROR
没有参数

还有疑问的话,可以这样写一个函数看看

int (foo())
{
return 0;
}

int main()
{
int i = foo();
}


这里很容易跟显式转换与构造临时对象混淆。
compiletime<sizeof(char)>=sizeof(int)>(ERROR());
会觉得是先构造ERROR() 先构造ERROR临时对象,然后再用这个临时对象来初始化一个compiletime<sizeof(char)>=sizeof(int)>的临时对象

其次,还容易错误的看作是
返回类型是compiletime<sizeof(char)>=sizeof(int)> 参数类型是ERROR(*)()的函数。
我在起先也当成是这个了。

现在,有一种办法,可以把compiletime<sizeof(char)>=sizeof(int)>(ERROR());解释成所说的临时对象。
(compiletime<sizeof(char)>=sizeof(int)>(ERROR()));
在外面加一个括号。这就明显是一个求值表达式了。
yshuise 2009-05-05
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 Jinhao 的回复:]
引用 13 楼 Jinhao 的回复:
compiletime <sizeof(char)>=sizeof(int)>(ERROR());

这也不是函数声明.

只是一个函数原型.
typedef compiletime <sizeof(char)>=sizeof(int)> return_type;
return_type(ERROR());

意思就是返回一个compiletime <sizeof(char)>=sizeof(int)> 对象的,参数为 返回一个ERROR对象的无参数的函数指针 的函数

所以,那个警告提醒的恰到好处.告诉你那不是在调用一个函数


本人不才,思考…
[/Quote]
我觉得你这个推论不对。因为函数需要返回类型,函数名,函数参数。
而临时对象只需要类型,参数。其他的类型都行,只不过对于模板编译器不能很好的识别,才会分不清楚。
实际上编译这个报的警告也是错误的。它误认为是函数的原因。这肯定是语法分析器,没有写好。
Jinhao 2009-05-05
  • 打赏
  • 举报
回复
[Quote=引用 24 楼 BuleRiver 的回复:]
而测试代码中将会调用false的类模板,这个时候将会用一个类ERROR的临时对象ERROR()来最为参数构造一个false的compiletime <false>对象
[/Quote]

不是这个,因为C++明确了那样的写法在不参照上下文的时候,是模棱两可的,表达式语句还是声明。再也就是括号的问题,是函数调用形式还是声明。
例如 int(int()); 区分成函数调用形式还是声明。在19楼已经说了。lz的问题其实和模板一点关系也没有。
BuleRiver 2009-05-05
  • 打赏
  • 举报
回复
具体请参考《C++设计新思维:范型编程与设计模式之应用》
BuleRiver 2009-05-05
  • 打赏
  • 举报
回复
[Quote=引用楼主 tangshuiling 的帖子:]
C/C++ code
代码简单描述如下:
template <bool> struct compiletime;
template<> struct compiletime<true>
{
compiletime(...) {}
};
template <> struct compiletime<false> {};
struct ERROR{};

compiletime<sizeof(char)>=sizeof(int)>(ERROR()); //测试代码出现编译警告

warning C4930: 'compiletime<false> ERROR(void)': prototyped function not called
(was a variable definition intended?)
ER…
[/Quote]
是不是因为这样:
LZ这里声明了一个模板类,compiletime,带一个非类型参数<bool>
然后分别特化了对于true和false两种类型的类,但是在bool为true时,给出了构造函数,并且这个构造函数可以接受任意个数和类型的参数,而在false的时候,却没有给出,但是编译器会给加上构造函数。而测试代码中将会调用false的类模板,这个时候将会用一个类ERROR的临时对象ERROR()来最为参数构造一个false的compiletime<false>对象,可能是这个时候和编译器合成的构造函数对不上号,所以出了警告信息
加载更多回复(16)

65,190

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧