C++11 Variadic Templates and Functor with a variable number of member variables?

So, I have been playing with C++11 for a few days now, and determined that I REALLY like "Variadic Templates". I have been changing over all of my templates to use this new feature, but I have run into a snag with attempting to change my Functor template classes. I dont think there is a way to declare a Functor to have an undefined number of different member variables.

Here is an example of one of my "Variadic Template Methods"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
template<typename T, typename... Args> static T* createObject(Args... args) 
    {
        T* derived = new T(args...);
        
        if(dynamic_cast<Base*>(derived))
        {
            return  derived;
        }
        
        else
        {
            delete derived;
            return NULL;
        }
    }


Here is an example of one of my current functor classes.
1
2
3
4
5
class BaseFunctor
{
protected:
    virtual void operator()()=0;
};


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
template <class T, class D1, class D2> class DerivedFunctor_2 : public BaseFunctor
{
private:
    //Data
    T* pt2Object;           // Pointer to object
    void (T::*fpt)(D1, D2); // Pointer to member function
    D1 data1;               // Copy of data
    D2 data2;               // Copy of data
    
public:
    //Constructor
    DerivedFunctor_2(T* _pt2Object, void(T::*_fpt)(D1, D2), D1 _data1, D2 _data2)
    {
        pt2Object = _pt2Object;  
        fpt=_fpt;
        data1 = _data1;
        data2 = _data2;
    };
    
    //Methods
    virtual void operator()()
    {
        (*pt2Object.*fpt)(data1, data2);
    };
};


The problem is I need to create a "new" functor for every class that uses a different number of arguments, as well as the fact that the code honestly gets kind of ugly when calling a functor using this method. What I would prefer is replacing "D1 data1 = _data1;, D2 data2 = _data2, etc" with something like "D_Args dargs = args...; Thus creating a functor that could be used to call a method using any number of different variables at any time. Does that explanation make sense? Any ideas if this is possible?

> I have been changing over all of my templates to use this new feature,
> but I have run into a snag with attempting to change my Functor template classes.

With C++11, you probably don't need these Functor template classes any more - the code could be refactored to use polymorphic call-wrappers along with polymorphic binders.



> The problem is I need to create a "new" functor for every class that uses a different number of arguments ...
> as well as the fact that the code honestly gets kind of ugly ...

If these functor classes are really needed, or if this is an academic exercise:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <functional>
#include <iostream>
#include <vector>

struct base_functor
{
    virtual ~base_functor() {}
    virtual void operator()() = 0 ;
};

template< typename TARGET, typename RESULT, typename... ARGS >
struct derived_functor : base_functor
{
    derived_functor( TARGET* ptr, RESULT ( TARGET::*pmfn )(ARGS...), ARGS... data )
       : fun( std::bind( pmfn, ptr, data... ) ) {}

    derived_functor( TARGET& ref, RESULT ( TARGET::*pmfn )(ARGS...), ARGS... data )
       : fun( std::bind( pmfn, ref, data... ) ) {}

    virtual void operator()() override { fun() ; }

    private: std::function< void() > fun ;
};

template< typename T, typename R, typename... ARGS > inline // helper to deduce the types
derived_functor<T,R,ARGS...> make_fun( T* p,  R( T::*pmf )( ARGS... ), ARGS... data)
{ return derived_functor<T,R,ARGS...>( p, pmf, data... ) ; }

template< typename T, typename R, typename... ARGS > inline // helper to deduce the types
derived_functor<T,R,ARGS...> make_fun( T& r,  R( T::*pmf )( ARGS... ), ARGS... data)
{ return derived_functor<T,R,ARGS...>( r, pmf, data... ) ; }


int main()
{
    struct test
    {
        int foo( int, char ) { std::cout << "int test::foo(int,char)\n" ; return 9 ; }
        void bar( long, double, test ) { std::cout << "void test::bar(long,double,test)\n" ; }
    } test_it, another ;

    auto f1 = make_fun( &test_it, &test::foo, 7, 'a' ) ;
    auto f2 = make_fun( test_it, &test::bar, 7L, 0.0, another ) ;

    std::vector< std::reference_wrapper<base_functor> > functors = { f1, f2 } ;
    for( auto& fn : functors ) fn() ;
}

Thank you for your response. After you mentioned std::bind, I found that was all I really needed to use. Apparently it does exactly what I was trying to emulate in a functor. Thank you!
To be honest, I'd have thought that lambdas would be a better solution than functors - The ability to capture variables by-reference in the lambda-specifier (i.e. [&] ) should take away the need for a variable number of function arguments most of the time.

The lambda will already have visibility of whatever you'd be passing; therefore, if you wanted to store a list of functions which each need to reference completely different data, you could probably get away with simply doing
1
2
3
4
5
6
7
8
9
10
11
12
13
14
    typedef std::function< void() > function_type;
    std::vector<function_type> callbacks;

    std::string str( "hello " );
    int n( 5 );
    double d( 5.5 );

    callbacks.push_back( [&]() { std::cout << str << n << std::endl;  } );
    callbacks.push_back( [&]() { std::cout << d << std::endl;  } );

    std::for_each( callbacks.begin(), callbacks.end(), []( function_type call )
    {
        call();
    });

Of course, I understand the impulse with a new toy such as variadic templates is to go crazy and use them everywhere, but if this is real code and not a purely toy/academic exercise, then I'd strongly suggest you consider lambdas instead.
Last edited on
Go crazy and use variadic templates everywhere, use lambdas everywhere, use std::bind() everywhere, ... Each has its place; each could be more appropriate in a particular context. As always, one size does not fit all.

Typically, a flxible design is not an either this or that design - variadic templates and callable objects (closures/lambdas, functors, call-wrappers, functions curried by std::bind) all co-exist very well. This allows the most appropriate choice to be made seamlessly on a per local-context basis. A typical example of a flexible design approach is std::threrad
1
2
3
4
5
6
7
8
class  thread  
{
    public:
        // ...
        template  < typename CALLABLE_OBJECT,  typename... ARGS >  
            explicit  thread( CALLABLE_OBJECT&& fn,  ARGS&&...  args );
        // ...
};

The callable object could be anything callable - a free function, a function object, a closure(lambda), a call-wrapper. The callable object could be not curried at all, or partially or fully curried with std::bind.


In general, if a short simple lambda can be written, it is preferrrable to a functor curried with std::bind(). Closures tend to make for clearer, more easily understandable code. When used within the same translation unit, they also generate more efficient code than std::bind() - calls through closures allow inlining, std::bind() calls are through pointers and are typically not inlined.


However, there are several situations where a lambda would not be the most appropriate choice:

Though arbitrarily complex lambdas are possible, lambdas work best when they are short, clear, concise and purely local-context driven. std::function<> with std::bind() is better suited for more complex or non-local scenarios.

There is no way for a lambda to capture a move-only type by value. The workaround is to capture the move-only type via a pointer - for instance a std::shared_ptr<std::ifstream>. Or capture by reference, when life-time-issues of the captured entity tend to complicate matters. In contrast, std::bind() bind is powered by rvalue references; a custom functor too can be, and either would lead to cleaner code.

Though lambdas can capture const objects by reference, there is no support for capture by reference to const. A custom functor or std::bind() can easily maintain const-correctness.

Lambdas can't be recursive. Again there is a work around - wrap the lambda in a call-wrapper like std::function<> and then call the wrapped closure from within the unwrapped closure. And again, the code would not be pretty. A functor has no such limitations.

Lambdas are not default constructible, and can't be directly used in a context where a default constructible callable object is required. This is an error:
std::unordered_set< int, decltype( [] ( int a, int b ) { return a%10 < b%10 ; } ) > my_set ;

Finally, a C++ lambda can't be polymorphic, a functor can be either compile-time or run-time polymorphic. This is a deliberate choice; lambdas are intended to be used in simple, local contexts. There is no insurmountable technical obstacle to having language support for polymorphic lambdas; For instance, boost::phoenix lambdas are polymorphic in nature:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <boost/phoenix/phoenix.hpp>
#include <string>
#include <iostream>

int main()
{
    using namespace boost::phoenix::arg_names ;

    auto plus = arg1 + arg2 ; // polymorphic lambda

    int i = 7, j = 9 ;
    double d = 3.456 ;
    std::string a = "abc", b = "defghijk" ;

    std::cout << plus(i,j) << ' ' << plus(i,d) << ' ' << plus(a,b) << ' '
              << plus( plus(a,b).c_str(), i ) << '\n' ;
}

Last edited on
auto plus = arg1 + arg2 ;
...
plus(i,j)

My heart just stopped.
Last edited on
Topic archived. No new replies allowed.