I had a problem compiling my code since it wasn't able to find a matching function on a template. I've narrowed down the problem to this example:
namespace cv
{
class FileNode
{ };
template<typename _Tp> static inline void operator >> (const FileNode& n, _Tp& value)
{
read(n, value, _Tp());
}
static inline void read(const FileNode& node, bool& value, bool default_value)
{ }
}
class K
{ };
namespace D
{
class A
{ };
}
template<class X>
static void read(const cv::FileNode& node, X& x, const X& default_value)
{
return;
}
using namespace D;
class B
{
void read(const cv::FileNode& fn)
{
A a;
fn >> a;
}
};
int main(int argc, char* argv[]) { }
On Gcc 9.10 I get the following error:
invalid initialization of reference of type 'bool&' from expression of type 'D::A' { read(n, value, _Tp()); }
On Visual Studio 2019:
Error C2664 'void cv::read(const cv::FileNode &,bool &,bool)': cannot convert argument 2 from '_Tp' to 'bool &'
I've found any of the following changes will make the code compiling:
class A
-> class A : public K
read
specialization for bool
cv
namespaceread
template inside namespace D
Unfortunately, none of the previous fixes is applicable to my original problem and I still don't really have an actual understanding on why exactly it's not able to find the read
template.
ADL strikes back:
in
template<typename _Tp> static inline void operator >> (const FileNode& n, _Tp& value)
{
read(n, value, _Tp());
}
read
is undeclared, so can only be found by ADL
So it will search in namespace associated to FileNode
(so cv
), and the ones associated to _Tp
.
when _Tp
is D::A
, it would be namespace D
.
and the only possible overload of read
is cv::read
which take bool
.
Moving declaration of read<T>
above cv::operator >>
solve the issue at it would also be considered with ADL.