Помогите наметапрограммировать или генерация parameter pack
От: Voivoid Россия  
Дата: 30.08.13 08:27
Оценка:
Доброго времени суток!

Хочется написать кроссплатформенную обертку над LoadLibrary/GetProcAddress ( кстати странно, что например в boost'е её нет ) примерно со следующим интерфейсом:

auto lib = LoadLib( "cool.dll" );
auto func = lib.GetFunc<int(int, int)>( "cool_func" );

int res = func( 1, 42 );

Хочется чтобы func был функциональным объектом, т.е. реализовывал operator() с аргументами указанными в GetFunc. Почему не просто указателем? Хочется внутри еще подсчет ссылок для проверки отсутствия живых функций на момент выгрузки библиотеки, но это к вопросу не относится

Подумалось, что func реализовать можно как-то так. Но вот как бы сгенерировать parameter pack? Да и возможно ли это сделать? И если нет, то есть ли другие пути решение этой проблемы?

#include "boost/type_traits/function_traits.hpp"

template <typename T, typename... Args>
struct func_helper {
    func_helper( T* a_func ) : i_func( a_func ) {}

    typename boost::function_traits<T>::result_type operator()( Args... args ) {
        return i_func( args... );
    }

    T* i_func;
};

template <typename T>
class func : func_helper<T, /* HELP ME */> {
public:
    func( T* a_func ) : func_helper( a_func ) {
    }
};
generate parameter pack variadic template
Re: Помогите наметапрограммировать или генерация parameter pack
От: jazzer Россия Skype: enerjazzer
Дата: 30.08.13 08:41
Оценка:
Здравствуйте, Voivoid, Вы писали:

V>Доброго времени суток!


V>Хочется написать кроссплатформенную обертку над LoadLibrary/GetProcAddress ( кстати странно, что например в boost'е её нет ) примерно со следующим интерфейсом:

V>auto lib = LoadLib( "cool.dll" );
V>auto func = lib.GetFunc<int(int, int)>( "cool_func" );

V>int res = func( 1, 42 );


Была предложена библиотека Boost.Extension, синтаксис как ты хочешь:
#include <boost/extension/extension.hpp>
  using namespace boost::extensions;
  std::string library_path = "libtutorial_1.extension";

  shared_library lib(library_path);

  boost::function<void (int)>
    f(lib.get<void, int>("boost_extension_hello_world"));

http://boost-extension.redshoelace.com/docs/boost/extension/index.html
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re: Помогите наметапрограммировать или генерация parameter pack
От: uzhas Ниоткуда  
Дата: 30.08.13 09:08
Оценка:
Здравствуйте, Voivoid, Вы писали:

V>Подумалось, что func реализовать можно как-то так. Но вот как бы сгенерировать parameter pack? Да и возможно ли это сделать? И если нет, то есть ли другие пути решение этой проблемы?

тычок в небо : http://www.boost.org/doc/libs/1_41_0/libs/function_types/example/interpreter.hpp
вдруг, чего полезное там найдете
Re: Помогите наметапрограммировать или генерация parameter pack
От: Conr Россия  
Дата: 30.08.13 09:26
Оценка:
Здравствуйте, Voivoid, Вы писали:

V>Доброго времени суток!


V>Хочется написать кроссплатформенную обертку над LoadLibrary/GetProcAddress ( кстати странно, что например в boost'е её нет ) примерно со следующим интерфейсом:


V>auto lib = LoadLib( "cool.dll" );

V>auto func = lib.GetFunc<int(int, int)>( "cool_func" );

V>int res = func( 1, 42 );


V>Хочется чтобы func был функциональным объектом, т.е. реализовывал operator() с аргументами указанными в GetFunc. Почему не просто указателем? Хочется внутри еще подсчет ссылок для проверки отсутствия живых функций на момент выгрузки библиотеки, но это к вопросу не относится


V>Подумалось, что func реализовать можно как-то так. Но вот как бы сгенерировать parameter pack? Да и возможно ли это сделать? И если нет, то есть ли другие пути решение этой проблемы?


V>
V>#include "boost/type_traits/function_traits.hpp"

V>template <typename T, typename... Args>
V>struct func_helper {
V>    func_helper( T* a_func ) : i_func( a_func ) {}

V>    typename boost::function_traits<T>::result_type operator()( Args... args ) {
V>        return i_func( args... );
V>    }

V>    T* i_func;
V>};

V>template <typename T>
V>class func : func_helper<T, /* HELP ME */> {
V>public:
V>    func( T* a_func ) : func_helper( a_func ) {
V>    }
V>};
V>


Как-то так можно попробовать:

#include <type_traits>

template <typename T>
class func;

template <typename F, typename ...Args>
class func<F(Args...)> : func_helper<F(Args...), Args...>
{
    
};


А лучше изменить func_helper:


template <typename R, typename... Args>
struct func_helper {
    typedef R (*FunctionType)(Args...);

    R operator()( Args... args ) {
        return i_func( args... );
    }

    FunctionType i_func;
};

template <typename T>
class func;

template <typename F, typename ...Args>
class func<F(Args...)> : public func_helper<F, Args...>
{
public:
};
Re: Помогите наметапрограммировать или генерация parameter pack
От: Voivoid Россия  
Дата: 30.08.13 09:27
Оценка:
Как часто и бывает, стоит только облечь проблему в письменную форму, как решение сразу же приходит в голову. Я в предыдущем посте на пустом месте все усложнил, а сделать-то можно все гораздо проще:

template <typename T>
class func {
public:
    func( T* a_func ) : i_func( a_func ) {
    }

    template <typename... Args>
    typename boost::function_traits<T>::result_type operator()( Args... args ) {
        return i_func( args... );
    }

private:
    T* i_func;
};
Re[2]: Помогите наметапрограммировать или генерация parameter pack
От: zaufi Земля  
Дата: 30.08.13 12:45
Оценка: 2 (1)
Здравствуйте, Voivoid, Вы писали:

V>Как часто и бывает, стоит только облечь проблему в письменную форму, как решение сразу же приходит в голову. Я в предыдущем посте на пустом месте все усложнил, а сделать-то можно все гораздо проще:


тогда уж

V>
V>template <typename T>
V>class func {
V>public:
V>    func( T* a_func ) : i_func( a_func ) {
V>    }

V>    template <typename... Args>
V>    typename boost::function_traits<T>::result_type operator()( Args&&... args ) {
V>        return i_func( std::forward<Args>(args)... );
V>    }

V>private:
V>    T* i_func;
V>};
V>
Re: Помогите наметапрограммировать или генерация parameter pack
От: ArtDenis Россия  
Дата: 30.08.13 13:12
Оценка:
У меня всё это нагенерено через Boost.Preprocessor. Variadic templates не использовал, т.к. их не поддерживает компилятор VC.
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
Re: Помогите наметапрограммировать или генерация parameter pack
От: c-smile Канада http://terrainformatica.com
Дата: 31.08.13 19:03
Оценка:
Здравствуйте, Voivoid, Вы писали:

Уже не помню откуда выдрал...

Сначала пример:


// declaring D2D1CreateFactory function reference:
DLOAD( D2D1CreateFactory, d2d1.dll, 
          HRESULT (WINAPI *)( D2D1_FACTORY_TYPE factoryType, REFIID riid, CONST D2D1_FACTORY_OPTIONS *pFactoryOptions, void **ppIFactory ) );

//usage:

if( D2D1CreateFactory ) // if it is available
    D2D1CreateFactory()(  factoryType, riid, &options, &pIFactory );


Единственная проблема: вызов таких функций требует дополнительных скобок ( )


имплементация, файл win-delayload.h "

#ifndef __win_delayload_h__
#define __win_delayload_h__

#include <windows.h>

namespace mswin 
{

template <class T>
class func_proxy  
{
protected:
    T         pfunc;
    HINSTANCE hlib;

    func_proxy() : pfunc( 0 ), hlib( 0 )
    {
    }

public:

    func_proxy( LPCTSTR pszLib, LPCSTR pszName ) : pfunc( 0 ), hlib( 0 )
    {
        load( pszLib, pszName );
    }
    
    virtual ~func_proxy()
    {
        unload(true);
    }
    
    operator bool() const
    { 
        return pfunc != 0; 
    }

    bool load( LPCTSTR pszLib, LPCSTR pszName )
    {
        assert( !hlib );
        hlib = ::LoadLibrary( pszLib );
        if( hlib )
        {
#ifdef PLATFORM_WINCE
            if( !( pfunc = (T) ::GetProcAddressA( hlib, pszName ) ) )
#else
            if( !( pfunc = (T) ::GetProcAddress( hlib, pszName ) ) )
#endif
                unload();
        }
        //assert( pfunc ); // func isn't resolved OK
        return pfunc != 0;
    }

    bool unload(bool from_dtor = false)
    {
        if( hlib && !from_dtor)
        {
      /* we should not call FreeLibrary from DllMain routine during process termination, 
         because this can result in a DLL being used after the system has executed its termination code 
      */
            BOOL res = ::FreeLibrary( hlib );
            assert( res );
            return res != 0;
        }
            pfunc = 0;
            hlib = 0;

        return false;
    }

    HINSTANCE instance()
    {
        return hlib;
    }

    T operator()()
    {
        assert(pfunc);
        return pfunc; 
    }
};

}

#ifndef stringizer
#define stringizer( x ) ( #x )
#endif


#define DLOAD( funcname, libname, type ) \
  mswin::func_proxy< type > funcname ( TEXT( #libname ), stringizer( funcname ) )

#define DLOADV( varname, funcname, libname, type ) \
  mswin::func_proxy< type > varname ( TEXT( #libname ), stringizer( funcname ) )

#endif // __win_delayload_h__
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.