maple
maple

Reputation: 1892

How to deduce C++ return type in template?

I have a functor, I want the return type to be deduced automatically. How can I do this?

template <typename _ScalarL, typename _ScalarR>
struct Multi
{
    DEDUCEDTYPE operator()(_ScalarL input1, _ScalarR input2) const
    {
        return input1 * input2;
    }
};

int main(){
    Multi<int, double> mt;
    mt(1,2.0);
}

how to get the DEDUCEDTYPE automatically?

Upvotes: 2

Views: 1033

Answers (2)

W.F.
W.F.

Reputation: 13988

Well I believe that before c++11 you are doomed to provide deduction by hand... You could create helper struct with specializations for that:

template <typename A, typename B>
struct deduce { };

template <>
struct deduce<int, double> {
   typedef double type;
};

template <typename ScalarL, typename ScalarR>
struct Multi
{
    typename deduce<ScalarL, ScalarR>::type operator()(ScalarL input1, ScalarR input2) const
    {
        return input1 * input2;
    }
};

int main(){
    Multi<int, double> mt;
    mt(1,2.0);
}

Edit:

The more general way of doing it would invoke however creating the hierarchy of priorities of the types that should be considered while deducing result type. Exemplary code:

#include <iostream>

template <typename T>
struct MoreGeneralNumber { };

template <>
struct MoreGeneralNumber<long>: MoreGeneralNumber<int> {};

template <>
struct MoreGeneralNumber<float>: MoreGeneralNumber<long> {};

template <>
struct MoreGeneralNumber<double>: MoreGeneralNumber<float> {};

typedef char (&yes)[1];
typedef char (&no)[2];

template <bool L, bool R, typename LT, typename RT>
struct MoreGeneral { };

template <bool R, typename LT, typename RT>
struct MoreGeneral<true, R, LT, RT> {
   typedef LT type;
};

template <typename LT, typename RT>
struct MoreGeneral<false, true, LT, RT> {
   typedef RT type;
};

template <typename B, typename D>
struct Host
{
  operator B*() const;
  operator D*();
};

template <typename B, typename D>
struct is_base_of
{
  template <typename T> 
  static yes check(D*, T);
  static no check(B*, int);

  static const bool value = sizeof(check(Host<B,D>(), int())) == sizeof(yes);
};

template <typename L, typename R>
struct Deduce: MoreGeneral<is_base_of<MoreGeneralNumber<R>, MoreGeneralNumber<L> >::value, 
                           is_base_of<MoreGeneralNumber<L>, MoreGeneralNumber<R> >::value, L, R >  {
};

template <typename ScalarL, typename ScalarR>
struct Multi
{
    typename Deduce<ScalarL, ScalarR>::type operator()(ScalarL input1, ScalarR input2) const
    {
        return input1 * input2;
    }
};

int main() {
   Multi<int, double> mt;
   std::cout << mt(1, 2.5) << std::endl; 
}

Upvotes: 3

iammilind
iammilind

Reputation: 70094

how to get the DEDUCEDTYPE automatically [with c++03]?

Automatic type deduction is not possible with C++03. As mentioned in other answer, you may have to manually create your own deducing specializations.

For C++11/C++14:

// For C++14, simply `auto` is enough
auto operator()(_ScalarL input1, _ScalarR input2) const
#if __cplusplus < 201402L
-> decltype(input1 * input2) // required for C++11
#endif

Upvotes: 3

Related Questions