On Fri, Dec 16, 2011 at 2:46 PM, Rhys Ulerich <rhys.ulerich@gmail.com> wrote:
'Afternoon,

I have a quick question on call traits and template argument
deduction.  I want to use call_traits' value_type and param_type to
deduce a signature like
 double desired_result(double const& x);
given an argument of type double.

Is there any way to get type deduction working on a snippet like
lousy_attempt (below) to produce my desired_result?

#include <boost/call_traits.hpp>

template<typename Scalar>
typename boost::call_traits<Scalar>::value_type
lousy_attempt(typename boost::call_traits<Scalar>::param_type x)
{
   return x;
}

int main()
{
   double y = 5;

   // Works...
   lousy_attempt<double>(y);

   // "No matching function call to lousy_attempt(double&)"
   lousy_attempt(y);

   return 0;
}

Thanks in advance,
Rhys

What you're doing can't work, as the compiler cannot deduce a template parameter based on matching to a nested type. Consider an arbitrary metafunction X<T>, with any number of specializations; how could the compiler deduce the correct "T" to match double (or whatever type) to X<T>::type? The compiler has no way of going from the ::type you're trying to match back to T.

If you really want this effect, you can use Boost.EnableIf:

template< class T >
typename boost::enable_if_c<
    boost::is_same<
        T const,
        typename boost::call_traits<T>::param_type
    >::value
>::type
f(T const x) { /*...*/ }

template< class T >
typename boost::enable_if_c<
    boost::is_same<
        T const &,
        typename boost::call_traits<T>::param_type
    >::value
>::type
f(T const & x) { /*...*/ }

Or, you can explicitly provide the template parameter to your definition of lousy_attempt. Or pass an extra, dummy argument to your function that presents T in a deduced context.

But I would generally recommend to just use T const &.

- Jeff