Boost logo

Boost Users :

From: Haroon Khan (haroon.khan_at_[hidden])
Date: 2006-12-02 14:03:13


Hi,
I tried the suggestion to call a template member function as follows,

  some_functor s;
    (bind(&some_functor::template_foo<int>, boost::ref(s),
         _1))(boost::cref(1));

and it simply would not compile. The compiler woulds always choke on
the some_functor::template_foo<int>.

The only thing I could get to compile was using a typedef as follows

    typedef void (another_functor::*foo_int) (int) ;
    foo_int ptr_to_fun = &another_functor::foo<int>;
    some_functor f;
    const some_functor &reff = f;
    int x(1);
    bind(ptr_to_fun, reff, _1); // This compiles

Unfortunately , this was'nt enough because everytime I tried calling
the bound function like

bind(ptr_to_fun, reff, _1)(x); // <- This does not compile

The compiler would choke again, saying that none of the overloaded
apply functions would apply. The error is as follows

 error C2665: 'boost::lambda::function_adaptor<Func>::apply' : none of
the 2 overloads could convert all the argument types
1> with
1> [
1> Func=void (__thiscall another_functor::* )(int)
1> ]

Finally my only work around was to wrap the call to the member
template function in another functor like the code snipped as follows,
and then using the bound function on it.

template<typename T>
struct local_struct
{
    void operator()(T x)
    {
        another_functor().foo<T>(x);
    }
};

and then binding to the overloaded operator () as follows

    bind(&(local_struct<int>::operator()),
boost::ref(local_struct<int>()), _1) (x);
    bind(&(local_struct<std::string>::operator()),
boost::ref(local_struct<std::string>()), _1)
        ( boost::cref(std::string("This is another bind call")) );

Its interesting that the compile time problems don't occur for free
template functions. I'm completely at a loss to explain why those
compile errors are occuring for member template functions, even though
all arguments are being passed by const reference. The complete code
listing is below for reference .

Thanks,
Haroon

struct another_functor{
    template<typename T>
    void foo(T x) ;
    template<typename T>
    void bar(){
        std::cout<< (boost::format("Return Type is %s in %s\n") %
typeid(T).name() %__FUNCTION__).str();

    }
};

template<>
void another_functor::foo<int>(int x) {
    std::cout<< (boost::format("%s(%d)\n") % __FUNCTION__ % x).str();
}

template<>
void another_functor::foo(float x) {
    std::cout<<(boost::format("%s(%f)\n")%__FUNCTION__%x).str();
}

template<>
void another_functor::foo(std::string x) {
    std::cout<<(boost::format("%s(\"%s\")\n")%__FUNCTION__%x).str();
}

template<typename T>
void free_func(T x){
    std::cout<<__FUNCTION__<<"("<<x<<")"<<std::endl;
}

template<typename T>
struct local_struct
{
    void operator()(T x)
    {
        another_functor().foo<T>(x);
    }
};

void test17()
{
    PRINT_FUNCTION_NAME;
    another_functor().foo<std::string>(std::string("Calling the string
function"));
    another_functor().foo<float>(1.32f);
    another_functor().foo<int>(1);
    another_functor().bar<int>();
    another_functor().bar<std::list<int> >();

    using namespace boost::lambda;

    std::cout<<typeid(free_func<int>).name()<<std::endl;
    bind(free_func<int>, _1)(boost::cref(1));

    typedef void (another_functor::*foo_int) (int) ;
    foo_int ptr_to_fun = &another_functor::foo<int>;
    some_functor f;
    const some_functor &reff = f;
    int x(1);
    bind(ptr_to_fun, reff, _1); // This compiles
    //bind(ptr_to_fun, reff, _1)(x); // <- This does not compile

    typedef void (another_functor::*bar_int) ();
    bar_int ptr_to_bar = &another_functor::bar<int>;
    bind(ptr_to_bar, reff); // Compiles !!!
    //bind(ptr_to_bar, reff)(); // Does not compile

    //The only work-around I could think of

    bind(&(local_struct<int>::operator()),
boost::ref(local_struct<int>()), _1) (x);
    bind(&(local_struct<std::string>::operator()),
boost::ref(local_struct<std::string>()), _1)
        ( boost::cref(std::string("This is another bind call")) );

}

On 11/30/06, Jaakko Järvi <jarvi_at_[hidden]> wrote:
> Hello Haroon,
>
>
> On Nov 30, 2006, at 12:37 AM, Haroon Khan wrote:
>
> > Jaakko,
> > Thanks for your reply, I tried some of your suggestions and they are
> > still giving me compile errors. Here is some code that Ive been
> > playing with. This was compiled in VC8.
> >
> > struct some_functor
> > {
> > private:
> > int x_;
> > public:
> > template<typename SOMETYPE>
> > some_functor& template_foo(SOMETYPE x){
> > std::cout<<boost::format("Calling %x.%s(%d)\n") % this %
> > __FUNCTION__%x;
> > return *this;
> > }
> > };
>
> > void test16
> > {
> > PRINT_FUNCTION_NAME;
> > using namespace boost::lambda;
> > int a[] = {1, 2, 3, 4, 5, 6, 7, 8};
> > std::vector<int> v(a, a+sizeof(a)/sizeof(int));
> >
> >
> > (bind(&(some_functor::template_foo<int>), some_functor(),
> > _1))(boost::cref(1))
> >
>
>
> The arguments given to bind at the time of call to bind (e.g.
> some_functor) are stored as
> const copies. Thus some_functor will be const, and when the functor
> is called, you are trying to
> call a non-const member with a const object.
>
> Here's one way to fix it:
>
> some_functor s;
> (bind(&some_functor::template_foo<int>, boost::ref(s),
> _1))(boost::cref(1));
>
> Cheers, Jaakko
>
> _______________________________________________
> Boost-users mailing list
> Boost-users_at_[hidden]
> http://lists.boost.org/mailman/listinfo.cgi/boost-users
>


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net