I get some warning with template and g++ -Os. Why ? How to remove these warning with -Os -Winline ?
我使用模板和g++ -Os得到一些警告。为什么?如何用-Os -Winline删除这些警告?
Edit 1: g++ v4.6.1 And if I replace uint32_t by unsigned int my main error is corrected: ( This bug has been reported: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52888 )
编辑1:g++ v4.6.1,如果我用unsigned int替换uint32_t,我的主要错误将被纠正:(这个错误已经被报告:http://gcc.gnu.org/bugzilla/show_bug.cgi?)id = 52888)
Event.h:109:12: attention : inlining failed in call to ‘uint32_t Event<ParamT>::attach(ListenerT*, bool (ListenerT::*)(ParamT)) [with ListenerT = Listener, ParamT = unsigned int, uint32_t = unsigned int]’: mismatched arguments [-Winline]
Edit 2: The following warning seem to be a g++ error (http://gcc.gnu.org/ml/gcc-help/2012-07/msg00029.html) ( I havn't any ~Player() ) inlining failed in call to ‘Player::~Player()’: call is unlikely and code size would grow [-Winline]
编辑2:下面的警告似乎是一个g++错误(http://gcc.gnu.org/ml/gcc-help/2012-07/msg00029.html)(我没有任何~Player())内联失败,调用“Player: ~Player()”:调用不太可能,代码大小也会增加[-Winline]
Edit 3: For removing the previous warning, add Player::~Player() __attribute__ ((noinline)) {}
编辑3:删除先前的警告,添加Player::~Player() __attribute__ ((noinline)) {}
.
。
Code for testing: Event.h
代码测试:Event.h
#ifndef EVENT_H
#define EVENT_H
#include <map>
#include <stdint.h>
/***************************************************************************//*!
* @brief Collect Listener
* @tparam ParamT Param type of the function
*/
template<typename ParamT>
class EventHandlerBase
{
public:
virtual bool notify( ParamT param ) = 0;
};
/***************************************************************************//*!
* @brief Conteneur d'un receveur d'event.
* @tparam ListenerT Object type
* @tparam ParamT Param type of the function
*/
template<typename ListenerT, typename ParamT>
class EventHandler : public EventHandlerBase<ParamT>
{
private:
typedef bool (ListenerT::*PtrMember)(ParamT);
private:
ListenerT* m_object;//!< Object listener
PtrMember m_member;//!< Function listener
public:
/********************************************************************//*!
* @brief Constructor
* @param[in] object Instance listener
* @param[in] member Function listener ( Function need to be a public member of {object} )
* @return[NONE]
*/
EventHandler( ListenerT* object, PtrMember member )
{
m_object = object;
m_member = member;
}
/*******************************************************************//*!
* @brief Emit a signal to listeners
* @param[in] param Data
* @return FALSE for breaking event loop
*/
bool notify( ParamT param )
{
return (m_object->*m_member)(param);
}
};
/***************************************************************************//*!
* @brief Event system
* @tparam ParamT Param type of the function
*/
template<typename ParamT>
class Event
{
private:
typedef typename std::map< uint32_t, EventHandlerBase<ParamT>* > HandlersMap;
private:
HandlersMap m_handlers;//!< Contient la liste des instances::fonctions en écoute sur cet event
uint32_t m_counter;//!< Permet de gérer les id
public:
/********************************************************************//*!
* @brief Constructor
* @return[NONE]
*/
Event()
{
m_counter = 0;
}
/********************************************************************//*!
* @brief Destructor
* @return[NONE]
*/
~Event()
{
typename HandlersMap::iterator it = m_handlers.begin();
for(; it != m_handlers.end(); it++)
{
if( it->second )
delete it->second;
}
}
/*******************************************************************//*!
* @brief Link a function and instance to this event
* @param[in] object Instance listener
* @param[in] PtrMember Function listener ( Function need to be a public member of {object} )
* @return Connection ID
*
* @warning DO NOT FORGET TO CALL Event::detach(uint32_t) if you delete {object}
*/
template<typename ListenerT>
uint32_t attach( ListenerT* object, bool (ListenerT::*PtrMember)(ParamT) )
{
m_handlers[m_counter] = new EventHandler<ListenerT,ParamT>(object, PtrMember);
m_counter++;
return m_counter-1;
}
/*******************************************************************//*!
* @brief Emit a signal to listeners
* @param[in] param Data
* @return[NONE]
*/
void notify( ParamT param )
{
typename HandlersMap::iterator it = m_handlers.begin();
for(; it != m_handlers.end(); it++)
{
if( !it->second->notify(param) )
return ;
}
}
/*******************************************************************//*!
* @brief Unlink a listener.
* @param[in] id Connection ID from Event::attach
* @return TRUE if removed
*/
bool detach( uint32_t id )
{
typename HandlersMap::iterator it = m_handlers.find(id);
if( it == m_handlers.end() )
return false;
delete it->second;
m_handlers.erase(it);
return true;
}
};
#endif // EVENT_H
Main.cpp
Main.cpp
#include <stdio.h>
#include "Event.h"
class Player
{
public:
Event<uint32_t> e_speed;
private:
uint32_t m_speed;
public:
Player()
{
m_speed = 15;
}
void setSpeed( uint32_t speed )
{
m_speed = speed;
e_speed.notify(speed);
}
};
class Listener
{
private:
Player m_player;
public:
Listener()
{
m_player.e_speed.attach(this, &Listener::SLOT_speed);
}
bool SLOT_speed( uint32_t speed )
{
printf("Speed changed to %u\n", speed);
return true;
}
Player* player()
{
return &m_player;
}
};
int main()
{
Listener l;
l.player()->setSpeed(42);
return 0;
}
Compile this code with: g++ -Os -W -Wall -Winline *.cpp You will get these warning:
用:g++ -Os -W -Wall -Winline来编译这段代码。cpp你会得到这些警告:
Event.h:109:12: attention : inlining failed in call to ‘uint32_t Event<ParamT>::attach(ListenerT*, bool (ListenerT::*)(ParamT)) [with ListenerT = Listener, ParamT = unsigned int, uint32_t = unsigned int]’: mismatched arguments [-Winline]
main.cpp:32:56: attention : appelé d'ici [-Winline]
main.cpp:4:7: attention : inlining failed in call to ‘Player::~Player()’: call is unlikely and code size would grow [-Winline]
main.cpp:31:3: attention : appelé d'ici [-Winline]
main.cpp:4:7: attention : inlining failed in call to ‘Player::~Player()’: call is unlikely and code size would grow [-Winline]
main.cpp:24:7: attention : appelé d'ici [-Winline]
main.cpp:4:7: attention : inlining failed in call to ‘Player::~Player()’: call is unlikely and code size would grow [-Winline]
main.cpp:24:7: attention : appelé d'ici [-Winline]
2 个解决方案
#1
0
It seems that g++ expands typedefs before using them as template arguments, but fails to expand typedefs not used as template arguments when comparing them with the former.
似乎在将typedef用作模板参数之前,g++会扩展typedef,但是在将typedef与前者进行比较时,却不能将typedef扩展为模板参数。
A simpler version of your code illustrates this :
您的代码的一个更简单的版本说明了这一点:
#include <iostream>
typedef unsigned int uint32_t;
template <typename T>
class Foo {
public :
template <typename C>
void fun(C* c, void (C::*f)(T)) {
(c->*f)(42);
}
};
class BarBad {
private :
Foo<uint32_t> foo;
public :
BarBad() {
foo.fun(this, &BarBad::fun);
}
void fun(uint32_t t) {
std::cout << t << std::endl;
}
};
template <typename T>
class BarGood {
private :
Foo<T> foo;
public :
BarGood() {
foo.fun(this, &BarGood<T>::fun);
}
void fun(T t) {
std::cout << t << std::endl;
}
};
int main(void) {
BarBad bb;
BarGood<uint32_t> bg;
return 0;
}
This code only gets a warning for the BarBad
code :
这段代码只对条形码发出警告:
test.cpp: In function ‘int main()’:
test.cpp:9: warning: inlining failed in call to ‘void Foo<T>::fun(C*, void (C::*)(T)) [with C = BarBad, T = unsigned int]’: function not considered for inlining
test.cpp:20: warning: called from here
In BarBad
, when calling Foo<uint32_t>::fun
, the type of the second parameter is void (BarBad::*)(uint32_t)
, but the called function expects void (BarBad::*)(unsigned int)
, and fails to see that uint32_t
and unsigned int
are the same types.
在BarBad中,当调用Foo
In BarGood<uint32_t>
, when calling Foo<uint32_t>::fun
, the type of the second parameter is void (BarGood<uint32_t>::*)(unsigned int)
, which matches what the called function expects.
在BarGood
This feels like a compiler bug to me. And a bit of searching turned up this bug report :
这让我感觉像是一个编译器bug。搜索结果显示:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52888
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52888
I haven't tested whether the solution there fixes this issue too, but it sounds like it would.
我还没有测试解决方案是否也能解决这个问题,但听起来似乎是这样。
#2
4
Your motivations are a bit unclear...
你的动机有点不清楚……
Do you want the warnings to go away? Remove the -Winline
options. That's what it does: it warns about non-inlined inline functions.
你想让警告消失吗?删除-Winline选项。这就是它所做的:它警告非内联内联函数。
Do you want these functions to be inlined, even if the code may get bigger/slower? You will have to play with the heuristics for inlining. There are several options you can try:
您是否希望这些函数是内联的,即使代码可能变得更大/更慢?你将不得不使用启发式方法进行内联。你可以尝试以下几种选择:
- Add
__attribute__(always_inline)
to the relevant functions. - 将__attribute__(always_inline)添加到相关函数中。
- Compile with
-finline-limit=N
with a bigN
. - 用-finline-limit=N和一个大N进行编译。
- Play with compiler options
--param NAME=VALUE
. There are tens of parameters that control inlining (max-inline-insns-single
,max-inline-insns-auto
,large-function-insns
,inline-unit-growth
, etc.) You can readinfo gcc
to get the details. - 使用编译器选项—param NAME=值。有几十个参数可以控制内衬(max-inline-insns-single, max-inline-insns-auto,大功能-insns, inline-unit-growth等),你可以阅读信息gcc来获取细节。
#1
0
It seems that g++ expands typedefs before using them as template arguments, but fails to expand typedefs not used as template arguments when comparing them with the former.
似乎在将typedef用作模板参数之前,g++会扩展typedef,但是在将typedef与前者进行比较时,却不能将typedef扩展为模板参数。
A simpler version of your code illustrates this :
您的代码的一个更简单的版本说明了这一点:
#include <iostream>
typedef unsigned int uint32_t;
template <typename T>
class Foo {
public :
template <typename C>
void fun(C* c, void (C::*f)(T)) {
(c->*f)(42);
}
};
class BarBad {
private :
Foo<uint32_t> foo;
public :
BarBad() {
foo.fun(this, &BarBad::fun);
}
void fun(uint32_t t) {
std::cout << t << std::endl;
}
};
template <typename T>
class BarGood {
private :
Foo<T> foo;
public :
BarGood() {
foo.fun(this, &BarGood<T>::fun);
}
void fun(T t) {
std::cout << t << std::endl;
}
};
int main(void) {
BarBad bb;
BarGood<uint32_t> bg;
return 0;
}
This code only gets a warning for the BarBad
code :
这段代码只对条形码发出警告:
test.cpp: In function ‘int main()’:
test.cpp:9: warning: inlining failed in call to ‘void Foo<T>::fun(C*, void (C::*)(T)) [with C = BarBad, T = unsigned int]’: function not considered for inlining
test.cpp:20: warning: called from here
In BarBad
, when calling Foo<uint32_t>::fun
, the type of the second parameter is void (BarBad::*)(uint32_t)
, but the called function expects void (BarBad::*)(unsigned int)
, and fails to see that uint32_t
and unsigned int
are the same types.
在BarBad中,当调用Foo
In BarGood<uint32_t>
, when calling Foo<uint32_t>::fun
, the type of the second parameter is void (BarGood<uint32_t>::*)(unsigned int)
, which matches what the called function expects.
在BarGood
This feels like a compiler bug to me. And a bit of searching turned up this bug report :
这让我感觉像是一个编译器bug。搜索结果显示:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52888
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52888
I haven't tested whether the solution there fixes this issue too, but it sounds like it would.
我还没有测试解决方案是否也能解决这个问题,但听起来似乎是这样。
#2
4
Your motivations are a bit unclear...
你的动机有点不清楚……
Do you want the warnings to go away? Remove the -Winline
options. That's what it does: it warns about non-inlined inline functions.
你想让警告消失吗?删除-Winline选项。这就是它所做的:它警告非内联内联函数。
Do you want these functions to be inlined, even if the code may get bigger/slower? You will have to play with the heuristics for inlining. There are several options you can try:
您是否希望这些函数是内联的,即使代码可能变得更大/更慢?你将不得不使用启发式方法进行内联。你可以尝试以下几种选择:
- Add
__attribute__(always_inline)
to the relevant functions. - 将__attribute__(always_inline)添加到相关函数中。
- Compile with
-finline-limit=N
with a bigN
. - 用-finline-limit=N和一个大N进行编译。
- Play with compiler options
--param NAME=VALUE
. There are tens of parameters that control inlining (max-inline-insns-single
,max-inline-insns-auto
,large-function-insns
,inline-unit-growth
, etc.) You can readinfo gcc
to get the details. - 使用编译器选项—param NAME=值。有几十个参数可以控制内衬(max-inline-insns-single, max-inline-insns-auto,大功能-insns, inline-unit-growth等),你可以阅读信息gcc来获取细节。