> >  > As to your suggestion: I don't think you can overload connect() 
> >  > specifically for a lambda with a specific signature ? 
> >  
> > No, but it's possible to check at compile time whether a function 
> > object is callable with a particular set of argument types, and 
> > dispatch to different implementations based on the result. If you 
> > think this is a reasonable approach, I'm happy to write some 
> > proof-of-concept code to demonstrate. 
> >  
> >  > As to how you can make it work: you can use std::bind() to bind away 
> >  > the argument. See for example the second example at : 
> >  > http://www.webtoolkit.eu/widgets/forms/push-button 
> >  
> > I think it would be nice if Wt did this adaptation step. 
>  
> Certainly, and I would appreciate a proof-of-concept ? 
>  
> This would mean that you can make it entirely an implementation detail  
> of connect(F f) with f a function object?

Yep. See the attached code file, which declares a template function
called 'call_with_zero_or_one_args' which takes a function object,
and calls it with an argument of a specific type if it can, or with
no arguments otherwise.

I am proposing that 'connect(F f)' be implemented in a similar way.

The implementation uses the C++11 features 'decltype' and 'extended
SFINAE', so it would need to be ifdef-ed out on compilers that don't
support these (and the current implementation used instead).
Boost.Config conveniently provides macros for testing the presence
of each C++11 feature [1], so the guard can be something like:

!defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_SFINAE_EXPR)

I don't know whether a C++03 implementation is possible; decltype
might be replaceable with BOOST_TYPEOF but I don't know whether the
extended SFINAE can be replaced by something else. In practice, a
C++11 implementation should be fine since the aim is to improve
support for C++11 lambdas.

Regards,
Nate

[1] 
http://www.boost.org/doc/libs/1_53_0/libs/config/doc/html/boost_config/boost_macro_reference.html#boost_config.boost_macro_reference.macros_that_describe_c__11_features_not_supported
                                          
// PART 1 - A metafunction that tests whether a function object
//          is callable with a single argument of a specified type.

#include <boost/mpl/if.hpp>
#include <boost/utility/declval.hpp>

template <typename F, typename Arg>
struct is_callable_with_argument
{
    typedef char (&no) [1];
    typedef char (&yes)[2];
    
    template <typename T> struct dummy;
    
    template <typename T>
    static yes check(dummy<decltype(boost::declval<T>()(boost::declval<Arg>()))>*);
    
    template <typename T>
    static no check(...);
    
    static const bool value = (sizeof(check<F>(0)) == sizeof(yes));
};

// PART 2 - A metafunction that converts the result of is_callable_with_argument
//          to a type tag.

struct zero_args_tag {};
struct one_arg_tag {};

template <typename F, typename Arg>
struct callable_with_argument_tag
{
    typedef typename boost::mpl::if_<is_callable_with_argument<F, Arg>,
                                     one_arg_tag,
                                     zero_args_tag>::type type;
};

// PART 3 - A function that uses callable_with_argument_tag to dispatch
//          to a different implementation based on whether the function
//          object is callable with a specific argument type.

struct ArgType {};  // the specific argument type

// implementation for a zero-argument function object
template <typename F>
void call_with_zero_or_one_args_impl(const F& f, zero_args_tag)
{
    f();
}

// implementation for a one-argument function object
template <typename F>
void call_with_zero_or_one_args_impl(const F& f, one_arg_tag)
{
    ArgType arg;
    f(arg);
}

// dispatching code
template <typename F>
void call_with_zero_or_one_args(const F& f)
{
    call_with_zero_or_one_args_impl(f, typename callable_with_argument_tag<F, ArgType>::type());
}

// PART 4 - Example usages of call_with_zero_or_one_args.

#include <boost/bind.hpp>

void zero_args() {}
void one_arg(ArgType) {}

struct zero_args_t
{
    void operator()() const {}
};

struct one_arg_t
{
    void operator()(ArgType) const {}
};

struct foo
{
    void bar1() const {}
    void bar2(ArgType) const {}
};

int main()
{
    call_with_zero_or_one_args([]{});
    call_with_zero_or_one_args([](ArgType){});
    
    call_with_zero_or_one_args(&zero_args);
    call_with_zero_or_one_args(&one_arg);
    
    call_with_zero_or_one_args(zero_args_t());
    call_with_zero_or_one_args(one_arg_t());

    foo f;
    call_with_zero_or_one_args(boost::bind(&foo::bar1, f));
    call_with_zero_or_one_args(boost::bind(&foo::bar2, f, _1));
}
------------------------------------------------------------------------------
Own the Future-Intel&reg; Level Up Game Demo Contest 2013
Rise to greatness in Intel's independent game demo contest.
Compete for recognition, cash, and the chance to get your game 
on Steam. $5K grand prize plus 10 genre and skill prizes. 
Submit your demo by 6/6/13. http://p.sf.net/sfu/intel_levelupd2d
_______________________________________________
witty-interest mailing list
witty-interest@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/witty-interest

Reply via email to