2

可変数の引数を持つオーバーロードのコードの重複 (または醜いマクロ) を避けるために、古いテンプレートの一部を可変長バージョンに置き換え始めました。

私が遭遇し、まだ解決されていない問題の 1 つは、次のとおりです。

これが私の例です:

    #include <tuple>

    // old version to be replaced
    namespace old_version
    {
        template<typename T> struct struct_const_deref { typedef T Type; };
        template<typename T> struct struct_const_deref < const T& > { typedef T Type; };

        template < typename F, typename T1 >
        void exec(F* pObj, void(F::*pFct)(T1))
        {
            typename struct_const_deref<T1>::Type t1;

            // some code that fills t1

            (pObj->*pFct)(t1);
        }

        template < typename F, typename T1 , typename T2 >
        void exec(F* pObj, void(F::*pFct)(T1, T2))
        {
            typename struct_const_deref<T1>::Type t1;
            typename struct_const_deref<T2>::Type t2;

            // some code that fills t1, t2

            (pObj->*pFct)(t1, t2);
        }
    }

    // new variadic version
    namespace variadic 
    {
        template< typename... Args > struct struct_const_deref_tuple { typedef std::tuple< Args... > Tuple; };
        template< typename... Args > struct struct_const_deref_tuple < const Args&... > { typedef std::tuple< Args... > Tuple; };

        template < typename F, typename... Args >
        void exec(F* pObj, void(F::*pFct)(Args... args))
        {
            typename struct_const_deref_tuple< Args... >::Tuple tN;

            // some code that fills tN

            // some helper template that 'extracts' the tuple and calls (pObj->*pFct)(ExtractedArgs...)
        }
    }

    struct Test
    {
        void foo(int i) {}
        void bar(const float& f, const int& i) {}
        void buu(const float& f, int i) {}
    };



    int main(int argc, char* argv[])
    {
        Test t;

        old_version::exec(&t, &Test::foo); // ok
        old_version::exec(&t, &Test::bar); // ok
        old_version::exec(&t, &Test::buu); // ok

        variadic::exec(&t, &Test::foo); // ok
        variadic::exec(&t, &Test::bar); // ok
        variadic::exec(&t, &Test::buu); // fails (the struct_const_deref_tuple does not 'catch' my case; 'tN' will be std::tuple<const float&, int>

        return 0;
    }

古いソリューションでは引数の数ごとにバージョンが必要だったので、可変引数のソリューションに置き換えたいと思います。

残念ながら、可変長バージョンは失敗します

Test::buu

なぜなら tN は

std::tuple<const float&, int> 

しかし、それは明らかにする必要があります

std::tuple<float, int> 

私が働くために。

どんなアイデアも歓迎します:)

4

2 に答える 2

2

本質的な問題はパック拡張です。また、簡単にするために type_traits から std::decay(c++11) または std::decay_t (c++14) を使用できます。次のコードは、c++14 でコンパイルする必要があります。

#include <tuple>
#include <type_traits>

// new variadic version
namespace variadic
{
    template < typename F, typename... Args >
    void exec(F* pObj, void(F::*pFct)(Args... args))
    {
        std::tuple<std::decay_t<Args>...> tN;

        // some code that fills tN

        // some helper template that 'extracts' the tuple and calls (pObj->*pFct)(ExtractedArgs...)
    }
}

struct Test
{
    void foo(int i) {}
    void bar(const float& f, const int& i) {}
    void buu(const float& f, int i) {}
};



int main(int argc, char* argv[])
{
    Test t;

    variadic::exec(&t, &Test::foo); // ok
    variadic::exec(&t, &Test::bar); // ok
    variadic::exec(&t, &Test::buu); // ok

    return 0;
}
于 2015-04-11T07:35:20.857 に答える