Since every operator needs to be a friend of every template specialization, you need to keep both template parameters free. I also found that you need to move the definition outside the class, though I'm not perfectly sure why:
template <typename T>
class box
{
// ...
template <typename A, typename B>
friend
auto operator+(const box<A>& left, const box<B>& right) -> box<decltype(std::declval<A>() + std::declval<B>())>;
};
template <typename A, typename B>
auto operator+(const box<A>& left, const box<B>& right) -> box<decltype(std::declval<A>() + std::declval<B>())>
{
return { left.value + right.value };
}
By the way, instead of the cumbersome auto -> decltype
construction, you could also use the simpler and more readable box<typename std::common_type<A, B>::type>
, or in C++14 box<std::common_type_t<A, B>>
.