Your friend template it its current form has a non-template dependency
on the parameter `T` of the surrounding class template `BST`. Such
templates are legal in C++, but they can only be defined directly at the
point of declaration. C++ provides no syntax for defining them
out-of-class. If you define it right there, you should be fine
#include <iostream>
template<typename T>
struct BST
{
template<typename L>
struct BSTNode
{
int val = 42;
template<typename M>
friend std::ostream& operator<<(std::ostream& out,
const BSTNode<M>& elem)
{
out << elem.val;
return out;
}
};
};
int main(int argc, char **argv)
{
BST<int>::BSTNode<int> n;
std::cout << n;
}
However, this is still quite weird. Why did you decide to have
parameterized template dependency on the parameter `L` of `BSTNode`, but
no template dependency on the parameter `T` of `BST`? Either get rid of
both dependencies, i.e. turn your your operator into a non-template
#include <iostream>
template<typename T>
struct BST
{
template<typename L>
struct BSTNode
{
int val = 42;
friend std::ostream& operator<<(std::ostream& out,
const BSTNode& elem)
{
out << elem.val;
return out;
}
};
};
int main(int argc, char **argv)
{
BST<int>::BSTNode<int> n;
std::cout << n;
}
(note that in this variant you will still have to define the operator
in-class)
or keep both dependencies
#include <iostream>
template<typename T>
struct BST
{
template<typename L>
struct BSTNode
{
int val = 42;
template<typename U, typename V>
friend std::ostream&
operator<<(std::ostream& out,
const BST<U>::template BSTNode<V>& elem);
};
};
template<typename U, typename V>
std::ostream&
operator<<(std::ostream& out,
const typename BST<U>::template BSTNode<V>& elem)
{
out << elem.val;
return out;
}
int main(int argc, char **argv)
{
BST<int>::BSTNode<int> n;
operator<< <int>(std::cout, n);
}
In this variant it will become possible to define the friend function
outside the class. However, this version is problematic (read: useless)
since parameter `U` is in non-deduced context. The only way to call such
operator would be through a function calls syntax with explicit
specification of at least the first template argument, as shown in the
example above.
Basically, long story short, when it comes to templates prefer to define
friend functions right there in-class. That will save you from dealing
with some weird and unpleasant peculiarities of the language .
--
Best regards,
Andrey.