#include <iostream>

class B;

class A {
  double d;
public:
  A(double a) : d(a) {}
  friend class B;
  double operator*(B& b); // auto operator*(B& b) -> decltype(d * B::i) と書けない
};

class B {
  int i;
public:
  B(int j) : i(j) {}
  friend class A;
  auto operator*(A& a) -> decltype(i * A::d) {
    return i * a.d;
  }
};

auto A::operator*(B& b) -> decltype(d * B::i)
{
  return d * b.i;
}

template<class T, class U>
auto mul(T x, U y) -> decltype(x * y)
{
  return x * y;
}

int main()
{
  A a(3.0);
  B b(5);

  std::cout << mul(a, b) << std::endl;
  std::cout << a * b << std::endl;
}