For various reasons I need to use 2 phase construction, furthermore the last phase is deferred and performed by another thread, some context:
...
#define BOOST_PP_LOCAL_MACRO(n) \
template < typename ConnectionType, BOOST_PP_ENUM_PARAMS(n, typename T) > \
boost::shared_ptr< ConnectionType > Connect( BOOST_PP_ENUM_BINARY_PARAMS(n, T, arg) ) \
{ \
boost::shared_ptr< ConnectionType > con( boost::make_shared< ConnectionType >() ); \
boost::mutex::scoped_lock sl( m_AddNetworkJobMutex ); \
m_NetworkJobs.push_back( boost::bind( static_cast< void ( ConnectionType::* )( BOOST_PP_ENUM_PARAMS(n,T) ) >( &ConnectionType::Init ), con, BOOST_PP_ENUM_PARAMS(n, arg) ) ); \
return con; \
}
#define BOOST_PP_LOCAL_LIMITS (1, 5)
#include BOOST_PP_LOCAL_ITERATE()
...
The problem here is that I want to select the best match possible from the overload set for ConnectionType::Init, but the cast is distinct and can't find a perfect match even if some of the arguments are convertible. So the questions becomes: Is it possible to somehow get the type & pointer to the best match from the overload set without actually calling it? Can't use anything which isn't available in C++03.
You can leverage lazy evaluation expression templates.
AFAIK bind expressions are precisely in that family (as are Boost Proto epxressions, Spirit Grammar parse expressions etc.).
Update finally got my act together. However, it only works with callable objects with overloaded operator(). I suppose you can use something like this as glue?
// TODO
in the code)result_of
for backgrounds on result types of polymorphic function objects)Here is a partial port of the C++11 demo (below) into C++03 + Boost:
#include <string>
#include <iostream>
#include <boost/bind.hpp>
#include <boost/typeof/typeof.hpp>
struct overloaded
{
typedef int result_type;
int operator()(const std::string& s) const { return 1; }
int operator()(double d) const { return 2; }
};
struct factory
{
template <typename T> struct result { typedef BOOST_TYPEOF_TPL(boost::bind(overloaded(), T())) type; };
template <typename T>
typename result<T>::type operator()(const T& t) const
{
return boost::bind(overloaded(), t);
}
};
int main()
{
overloaded foo;
// based on local bind expression:
BOOST_AUTO(unresolved, boost::bind(foo, _1));
std::cout << unresolved("3.14") << std::endl; // should print 1
std::cout << unresolved(3.14) << std::endl; // should print 2
// based on a factory function template
factory makefoo;
std::string str("3.14"); // TODO get rid of this explicit instanciation?
std::cout << makefoo(str)() << std::endl; // should print 1
std::cout << makefoo(3.14)() << std::endl; // should print 2
}
As a simple example, this should work alright:
#include <string>
#include <iostream>
#include <functional>
using namespace std::placeholders;
struct overloaded
{
int operator()(const std::string& s) const { return 1; }
int operator()(double d) const { return 2; }
};
template <typename T>
auto makefoo(const T& t) -> decltype(std::bind(overloaded(), t))
{
return std::bind(overloaded(), t);
}
int main()
{
overloaded foo;
// based on local bind expression:
auto unresolved = std::bind(foo, _1);
std::cout << unresolved(3.14) << std::endl; // should print 2
std::cout << unresolved("3.14") << std::endl; // should print 1
// based on a factory function template
std::cout << makefoo(3.14)() << std::endl; // should print 2
std::cout << makefoo("3.14")() << std::endl; // should print 1
}