1

テンプレートとg++-Osで警告が表示されます。なんで ?-Os -Winlineでこれらの警告を削除するにはどうすればよいですか?

編集1:g ++v4.6.1そしてuint32_tunsignedintに置き換えると、主なエラーが修正されます:(このバグが報告されています: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]

編集2:次の警告はg ++エラーのようです(http://gcc.gnu.org/ml/gcc-help/2012-07/msg00029.html)(私は〜Player()を持っていません)inlining failed in call to ‘Player::~Player()’: call is unlikely and code size would grow [-Winline]

編集3:前の警告を削除するには、追加しますPlayer::~Player() __attribute__ ((noinline)) {}

テスト用のコード: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

#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;
}

このコードを次のコマンドでコンパイルします。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]
4

2 に答える 2

5

あなたの動機は少し不明です...

警告を消したいですか?オプションを削除し-Winlineます。インライン化されていないインライン関数について警告します。

コードが大きくなったり遅くなったりしても、これらの関数をインライン化しますか? インライン化のヒューリスティックをいじる必要があります。試すことができるいくつかのオプションがあります。

  • 関連する関数に追加__attribute__(always_inline)します。
  • -finline-limit=N大きな でコンパイルしNます。
  • コンパイラ オプションで遊んで--param NAME=VALUEください。インライン化を制御するパラメーターは数十あります ( max-inline-insns-singlemax-inline-insns-autolarge-function-insnsinline-unit-growthなど)。詳細を読むために読むことができますinfo gcc
于 2012-07-30T15:39:51.670 に答える
0

g++ は、テンプレート引数として使用する前に typedef を展開しますが、前者と比較すると、テンプレート引数として使用されていない typedef の展開に失敗しているようです。

あなたのコードのより単純なバージョンはこれを示しています:

#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;
}

このコードは、BarBadコードの警告のみを受け取ります:

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

ではBarBad、 を呼び出すときFoo<uint32_t>::fun、2 番目のパラメータの型は ですvoid (BarBad::*)(uint32_t)が、呼び出された関数は を期待void (BarBad::*)(unsigned int)し、それを認識できず、uint32_tunsigned intは同じ型です。

ではBarGood<uint32_t>、 を呼び出すときFoo<uint32_t>::fun、2 番目のパラメータの型は です。これはvoid (BarGood<uint32_t>::*)(unsigned int)、呼び出された関数が期待するものと一致します。

これは私にとってコンパイラのバグのように感じます。少し検索すると、このバグレポートが見つかりました:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52888

そこにあるソリューションでこの問題も修正されるかどうかはテストしていませんが、修正されるようです。

于 2012-07-31T08:45:35.150 に答える