Reputation: 33
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.
Upvotes: 3
Views: 202
Reputation: 3506
Normally, I would separate the classes and the namespaces to different .hpp files, which automatically, will force you to make the function:
template<typename _Tp> static inline void operator >> (const FileNode& n, _Tp& value)
To be declared before the namespaces which use it (like cv
).
I think that the best way to avoid this kind of problems is to clean your code, and to make it as separate and independent as you can. This way, whenever you want to use this unique read
function in another namespaces, you won't need to put the new namespaces inside this file, or alternative include all the namespaces that are currently in this file.
Upvotes: 0
Reputation: 217085
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.
Upvotes: 1