This is because the argument type, DerivedB<DerivedA<double> >
is not a derived class of BaseB<bderived1, BaseA<aderived1,datatype> >
: The arguments of operator+
have for their base class's second template argument passed the type DerivedA<double>
(which is datatype
) but the operator+
's function parameter specifies BaseA<aderived1,datatype>
as second template argument.
Since with these many types in there it's quite convoluted, let's make a simplier example
template<typename T>
struct B { };
template<typename T>
struct D : B<T> { };
struct base { };
struct derived : base { };
Now, let's see how these behave
template<typename T>
void f(B<T> const&);
void g(B<base> const&);
void h(B<derived> const&);
int main() {
D<derived> dd;
f(dd); // works, like your first case
h(dd); // works too (just not deduced).
g(dd); // does *not* work, just like your second case
}
The C++ Standard specifies that derived->base conversions are considered when matching a deduced function parameter type. That's why file << "hello"
works: The operator is defined in terms of basic_ostream<C,T>
even though file
really could be an basic_fstream
(derived class of it). This applies in your first case. But in your second case you try to deduce a parameter that's entirely not a base class of the argument passed.