2

I wanted to create these function templates you see below. Their purpose is to compare functors, but I needed to cover a special case for the boost.bind type of functors.

template<typename R, typename F, typename L>
void compare(boost::_bi::bind_t<R, F, L>& lhs, boost::_bi::bind_t<R, F, L>& rhs)
{
    std::cout << lhs.compare(rhs) << std::endl;
}

template<typename T>
void compare(T lhs, T rhs)
{
    std::cout << (lhs == rhs) << std::endl;
}

The problem is that when I do compare(boost::bind(func, 1), boost::bind(func, 1)), the compiler tries to use the second template. If I comment out the second one, it will correctly use the one specialized for the boost.bind type and everything will work fine.

How can I make it choose the correct function template to use?

Paul Manta
  • 30,618
  • 31
  • 128
  • 208
  • 1
    It looks like you are relying on a type that is a boost implementation private type. Are you sure you have exactly the right type for what you are passing in? If there's any sort of implicit conversion required to use the first template then the second template will be preferred as it can instantiated with the original types and hence be a better match. – CB Bailey Jul 31 '11 at 06:25
  • I first did `int i = boost::bind(func, 1)` to get the compiler to tell me what bind returns. Besides, the [function_equal templates](http://www.boost.org/doc/libs/1_47_0/boost/bind/bind.hpp) also take bind_t as arguments, so it should be safe for me to do that as well. – Paul Manta Jul 31 '11 at 06:32
  • 2
    Just looked up `boost::bind` and it returns its parameter by value so `compare(boost::find(func, 1), boost::bind(func, 1))` shouldn't use the first template as you can't bind a temporary to a non-const reference. If you add `const` to the first then it should be OK. As to why it works if you comment out the more general template, I'm not quite sure. On my implementation I do get an error when the general template is instantiated. – CB Bailey Jul 31 '11 at 06:38
  • @Charles Yup, it works. Add that as an answer so I can accept it. :) – Paul Manta Jul 31 '11 at 06:44

1 Answers1

1

boost::bind returns a value which can't be bound to a non-const reference. Your better specialized template needs to take it's arguments by value or by const reference otherwise it won't be considered in the call: compare( boost::bind(func, 1), boost::bind(func, 1) ).

This test program compiles and works correctly on my platform.

#include <boost/bind/bind.hpp>
#include <iostream>
#include <ostream>

template<typename R, typename F, typename L>
void compare(const boost::_bi::bind_t<R, F, L>& lhs
                 , const boost::_bi::bind_t<R, F, L>& rhs)
{
    std::cout << lhs.compare(rhs) << std::endl;
}

template<typename T>
void compare(T lhs, T rhs)
{
    std::cout << (lhs == rhs) << std::endl;
}

void func(int) {}

int main()
{
    compare( boost::bind(func, 1), boost::bind(func, 1) );
}
CB Bailey
  • 755,051
  • 104
  • 632
  • 656