1

The variadic template of C++ is powerful, but it's hard to write such code. Here comes my question: how to pass the construction of Class(see following code snippet) through template?

Note: because I want get a general solution, so the arguments of construction must be variadic. Besides, I want set default values of each argument.

Anybody could help me?

#include <iostream>
#include <utility>

template< typename R, typename C, typename... Args>
class delegate
{
public:
    template<R(C::*F)(Args...)>
    struct adapter 
    {
        static R invoke_no_fwd(Args... args) 
        { 
            C t; // how to pass the construction function of C through template??? and set default value for each argument
            return (t.*F)(args...); 
        }
    };
};

class Class 
{
public:
    Class(int param)
        : m_val(param)
    {}
    void print(int v) 
    {
        std::cout << "Class: " << v + m_val << std::endl;
    }
private:
    int m_val;
};

int main(int argc, char** argv) 
{
    using namespace std;
    // because the below code doesn't contain construction info, so it won't compile

    typedef void(*function_t)(int);
    function_t ptrFunc = (delegate<void, Class, int>::adapter<&Class::print>::invoke_no_fwd);
    auto type = (delegate<void, Class, int>::adapter<&Class::print>::invoke_no_fwd);
    cout << typeid(type).name() << endl;
    return 0;
}
Triumphant
  • 948
  • 1
  • 11
  • 28
  • Why don't you use `std::function` ? Are you open to it, or do you really want to rewrite everything yourself ? – quantdev Aug 25 '14 at 07:42
  • @quantdev no, i want to write a adapter which can convert non-static member function to c-style function pointer. my purpose is to make develop MFC more conveient. the existing API interface can't be changed. it's the secret of Microsoft – Triumphant Aug 25 '14 at 07:50
  • But `std::function` can convert to C-style function ptr too... – quantdev Aug 25 '14 at 07:52
  • @quantdev, no definitely not. have a look at this: http://stackoverflow.com/questions/18370396/why-cant-stdfunction-bind-to-c-style-variadic-functions – Triumphant Aug 25 '14 at 07:57
  • You're talking about c-style variadics functions, ala `printf`, then. – quantdev Aug 25 '14 at 08:01
  • From where do you want to provide the constructor parameters ? – Jarod42 Aug 25 '14 at 09:00
  • @Jarod42, I want to add the parameter here template – Triumphant Aug 25 '14 at 09:06

2 Answers2

1

You may do the following with std::integral_constant<typename T, T>:

template< typename R, typename C, typename... Args>
class delegate
{
public:
    template<R(C::*F)(Args...), typename ... Ts>
    struct adapter {
        static R invoke_no_fwd(Args... args) {
            C t((Ts::value)...);
            return (t.*F)(args...);
        }
    };
};

And use it like:

int main()
{
    //using namespace std;

    typedef void(*function_t)(int);
    function_t ptrFunc = (delegate<void, Class, int>::adapter<&Class::print, std::integral_constant<int, 42> >::invoke_no_fwd);
    auto type = (delegate<void, Class, int>::adapter<&Class::print, std::integral_constant<int, 42>>::invoke_no_fwd);
    ptrFunc(-42);
    type(0);
    return 0;
}

Live example.

Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • there are compiling errors in Visual Studio 2013:1>Console.cpp(12): error C3520: 'Ts' : parameter pack must be expanded in this context 1> Console.cpp(11) : while compiling class template member function 'void delegate::adapter>::invoke_no_fwd(int)' 1> Console.cpp(37) : see reference to function template instantiation 'void delegate::adapter>::invoke_no_fwd(int)' being compiled 1> Console.cpp(37) : see reference to class template instantiation – Triumphant Aug 25 '14 at 09:41
  • 1
    @Triumphant: Adding extra parents around `Ts::value` fix compilation with VS2013. Edited – Jarod42 Aug 25 '14 at 09:47
  • it works, you are a expert on template programming. thank you so much – Triumphant Aug 25 '14 at 09:55
  • another question, how about my constructor function want 'const char*' parameter, see my new question: http://stackoverflow.com/questions/25580294/c-11stdintegral-constantchar-kernel32-dll-wont-compile , could you rewrite your answer by referring this question: http://stackoverflow.com/questions/25598265/how-to-construct-class-whose-constructor-function-might-have-multiple-parameter ? – Triumphant Sep 01 '14 at 07:21
0

alloctor uses macro to call destructor.

template<class _Ty> inline
    void _Destroy(_Ty _FARQ *_Ptr)
    {   // destroy object at _Ptr
    _DESTRUCTOR(_Ty, _Ptr);
    }

#define _DESTRUCTOR(ty, ptr)    (ptr)->~ty()

can this solve you problem?

wuqiang
  • 634
  • 3
  • 8