在 headers 之间调用时,模板实例化无法匹配重载流运算符的参数列表
Template instantiation unable to match argument list for overloaded stream operator when invoked between headers
注意:我以前没有遇到过这个问题!我的 to_string 方法工作得很好,模板实例化为我的 Point class 找到了正确的重载,我已经使用它几个月了!但是最后一次提交出了点问题,在一个源文件中我收到了这个 well-known 错误消息(仅在这个源文件中,在其他地方 mx::to_string(mx::Point) 可以正常工作) .我无法弄清楚可能是什么原因,因为我没有注意到任何可能搞砸的线路。
Plus 把流运算符重载的相关问题都扫了一遍,没找到解决办法。
所以我有一个观点class:
#ifndef MXBASIC_UTILITIES_H
#define MXBASIC_UTILITIES_H
#include <ostream>
#include <string>
namespace mx{
class Point;
}
class mx::Point
{
public:
Point();
Point(int x, int y);
int getX() const;
int getY() const;
int& getX();
int& getY();
//...
};
inline mx::Point::Point() : _x(0), _y(0) {}
inline mx::Point::Point(int x, int y) : _x(x), _y(y) {}
inline int mx::Point::getX() const { return _x; }
inline int mx::Point::getY() const { return _y; }
inline int& mx::Point::getX() { return _x; }
inline int& mx::Point::getY() { return _y; }
// THE OVERLOAD:
inline std::ostream& operator<<(std::ostream& os, const mx::Point& point){
return os << '(' << point.getX() << ',' << point.getY() << ')';
}
#endif
一个名为 header 的 helpertypes.h 文件,其中我有 to_string 函数:
#ifndef HELPERTYPES_H
#define HELPERTYPES_H
#include <iostream>
#include <cstdint>
#include <memory>
#include <sstream>
#include <string>
// ...
namespace mx{
template<typename T>
std::string to_string(const T& val)
{
std::ostringstream os;
os.flags(std::ios::fixed);
os.precision(2);
os << val; // getting error here as of recently, both in MinGW 4.7.3 and MSVC15
return os.str();
}
}
#endif
完整的错误信息:
此处更具可读性:pastebin.com/gFdFezrV
MSVC15:
2>c:(...)\classes\helpertypes.h(87): error C2679: binary '<<': no
operator found which takes a right-hand operand of type 'const
mx::Point' (or there is no acceptable conversion) 2> c:\program files
(x86)\microsoft visual studio 14.0\vc\include\ostream(495): note:
could be 'std::basic_ostream>
&std::basic_ostream>::operator
<<(std::basic_streambuf> *)' 2>
c:\program files (x86)\microsoft visual studio
14.0\vc\include\ostream(475): note: or 'std::basic_ostream>
&std::basic_ostream>::operator <<(const
void *)' 2> c:\program files (x86)\microsoft visual studio
14.0\vc\include\ostream(455): note: or 'std::basic_ostream>
&std::basic_ostream>::operator <<(long
double)' 2> c:\program files (x86)\microsoft visual studio
14.0\vc\include\ostream(435): note: or 'std::basic_ostream>
&std::basic_ostream>::operator <<(double)'
2> c:\program files (x86)\microsoft visual studio
14.0\vc\include\ostream(415): note: or 'std::basic_ostream>
&std::basic_ostream>::operator <<(float)'
2> c:\program files (x86)\microsoft visual studio
14.0\vc\include\ostream(395): note: or 'std::basic_ostream>
&std::basic_ostream>::operator <<(unsigned
__int64)' 2> c:\program files (x86)\microsoft visual studio 14.0\vc\include\ostream(375): note: or 'std::basic_ostream>
&std::basic_ostream>::operator
<<(__int64)' 2> c:\program files (x86)\microsoft visual studio
14.0\vc\include\ostream(355): note: or 'std::basic_ostream>
&std::basic_ostream>::operator <<(unsigned
long)' 2> c:\program files (x86)\microsoft visual studio
14.0\vc\include\ostream(335): note: or 'std::basic_ostream>
&std::basic_ostream>::operator <<(long)'
2> c:\program files (x86)\microsoft visual studio
14.0\vc\include\ostream(315): note: or 'std::basic_ostream>
&std::basic_ostream>::operator <<(unsigned
int)' 2> c:\program files (x86)\microsoft visual studio
14.0\vc\include\ostream(290): note: or 'std::basic_ostream>
&std::basic_ostream>::operator <<(int)' 2>
c:\program files (x86)\microsoft visual studio
14.0\vc\include\ostream(270): note: or 'std::basic_ostream>
&std::basic_ostream>::operator <<(unsigned
short)' 2> c:\program files (x86)\microsoft visual studio
14.0\vc\include\ostream(236): note: or 'std::basic_ostream>
&std::basic_ostream>::operator <<(short)'
2> c:\program files (x86)\microsoft visual studio
14.0\vc\include\ostream(216): note: or 'std::basic_ostream>
&std::basic_ostream>::operator <<(bool)'
2> c:\program files (x86)\microsoft visual studio
14.0\vc\include\ostream(209): note: or 'std::basic_ostream>
&std::basic_ostream>::operator
<<(std::ios_base &(__cdecl *)(std::ios_base &))' 2> c:\program files
(x86)\microsoft visual studio 14.0\vc\include\ostream(202): note: or
'std::basic_ostream>
&std::basic_ostream>::operator
<<(std::basic_ios> &(__cdecl
*)(std::basic_ios> &))' 2> c:\program files (x86)\microsoft visual studio 14.0\vc\include\ostream(196):
note: or 'std::basic_ostream>
&std::basic_ostream>::operator
<<(std::basic_ostream> &(__cdecl
*)(std::basic_ostream> &))' 2> c:\program files (x86)\microsoft visual studio 14.0\vc\include\ostream(692):
note: or 'std::basic_ostream>
&std::operator
<<>(std::basic_ostream>
&,const char *)' 2> c:\program files (x86)\microsoft visual studio
14.0\vc\include\ostream(739): note: or 'std::basic_ostream> &std::operator
<<>(std::basic_ostream>
&,char)' 2> c:\program files (x86)\microsoft visual studio
14.0\vc\include\ostream(777): note: or 'std::basic_ostream> &std::operator
<<>(std::basic_ostream>
&,const char *)' 2> c:\program files (x86)\microsoft visual studio
14.0\vc\include\ostream(824): note: or 'std::basic_ostream> &std::operator
<<>(std::basic_ostream>
&,char)' 2> c:\program files (x86)\microsoft visual studio
14.0\vc\include\ostream(950): note: or 'std::basic_ostream> &std::operator
<<>(std::basic_ostream>
&,const signed char *)' 2> c:\program files (x86)\microsoft visual
studio 14.0\vc\include\ostream(957): note: or
'std::basic_ostream> &std::operator
<<>(std::basic_ostream>
&,signed char)' 2> c:\program files (x86)\microsoft visual studio
14.0\vc\include\ostream(964): note: or 'std::basic_ostream> &std::operator
<<>(std::basic_ostream>
&,const unsigned char *)' 2> c:\program files (x86)\microsoft visual
studio 14.0\vc\include\ostream(971): note: or
'std::basic_ostream> &std::operator
<<>(std::basic_ostream>
&,unsigned char)' 2> c:\program files (x86)\microsoft visual studio
14.0\vc\include\ostream(981): note: or 'std::basic_ostream> &std::operator
<<,mx::Point>(std::basic_ostream>
&&,const _Ty &)' 2> with 2> [ 2>
_Ty=mx::Point 2> ] 2> c:\program files (x86)\microsoft visual studio 14.0\vc\include\ostream(1019): note: or
'std::basic_ostream> &std::operator
<<>(std::basic_ostream>
&,const std::error_code &)' 2> c:\program files (x86)\microsoft
visual studio 14.0\vc\include\random(2568): note: or
'std::basic_ostream> &std::operator
<<>(std::basic_ostream>
&,const std::bernoulli_distribution &)' 2> c:\program files
(x86)\microsoft visual studio 14.0\vc\include\thread(246): note: or
'std::basic_ostream> &std::operator
<<>(std::basic_ostream>
&,std::thread::id)' 2> c:(...)\classes\helpertypes.h(87): note:
while trying to match the argument list '(std::ostringstream, const
mx::Point)' 2>
c:(...)\classes(...)\entity\tinyent\tinyent.cpp(1502): note: see
reference to function template instantiation 'std::string
mx::to_string(const T &)' being compiled 2> with
2> [ 2> T=mx::Point 2> ]
MinGW 4.7.3:
In file included from jni/../../Classes/utilities/pattern/pat.h:5:0,
from jni/../../Classes/(...)/entity/tinyent/../ent.h:3,
from jni/../../Classes/(...)/entity/tinyent/tinyent.h:2,
from jni/../../Classes/(...)/entity/tinyent/tinyent.cpp:1:
jni/../../Classes/helpertypes.h: In instantiation of 'std::string
mx::to_string(const T&) [with T = mx::Point; std::string =
std::basic_string]':
jni/../../Classes/(...)/entity/tinyent/tinyent.cpp:1502:20: required
from here jni/../../Classes/helpertypes.h:87:5: error: cannot bind
'std::basic_ostream' lvalue to 'std::basic_ostream&&' os
<< val;
^ In file included from jni/../../Classes/utilities/pattern/abspat.h:6:0,
from jni/../../Classes/utilities/pattern/pat.h:3,
from jni/../../Classes/(...)/entity/tinyent/../ent.h:3,
from jni/../../Classes/(...)/entity/tinyent/tinyent.h:2,
from jni/../../Classes/(...)/entity/tinyent/tinyent.cpp:1:
C:/Users/(...)/Documents/libs/android-ndk-r10e/sources/cxx-stl/gnu-libstdc++/4.9/include/ostream:602:5:
note: initializing argument 1 of 'std::basic_ostream<_CharT, _Traits>&
std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&)
[with _CharT = char; _Traits = std::char_traits; _Tp =
mx::Point]'
operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x)
^
触发实例化的地方:
tinyent.h
#pragma once
#include <string>
#include "ent.h"
#include "mxbasic_utilities.h" // definition of my overload included!
class TinyEnt : public Ent
{
public:
// ...
virtual std::string toString() const override;
private:
// ...
int _posX, posY;
};
tinyent.cpp
#include "tinyent.h"
// ...
std::string toString() const
{
return std::string("TinyEnt ") + mx::to_string(id()) + " at " // decltype(id()) is ULL, no problem here
+ mx::to_string(mx::Point(_posX, _posY)); // place of instantiation, overload not found
}
如果我将我的 to_string 函数的定义放在这个 toString 函数的前面,它就可以工作:
备选tinyent.cpp
#include "tinyent.h"
template<typename T>
std::string to_string(const T& val)
{
std::ostringstream os;
os.flags(std::ios::fixed);
os.precision(2);
os << val;
return os.str();
}
std::string toString() const
{
return std::string("TinyEnt ") + mx::to_string(id()) + " at "
+ ::to_string(mx::Point(_posX, _posY)); // no problems this way
}
我完全不知道该怎么办。我检查了包括
层次结构如果可能有递归包含,则没有(helpertypes.h
仅取决于 stl headers)。我试过从 ground 0 重建,并尝试使用不同的编译器。您有任何提示可能出了什么问题吗?
编辑:
在我的 mx::to_string 函数中使用完整命名空间限定时(例如:::operator(os, val);
),我收到不同的错误消息。当输入 size_t(在本例中为 unsigned int)时,实例化会引发歧义错误,就好像在第一轮参数查找中找不到它一样。
In file included from jni/../../Classes/utilities/pattern/pat.h:5:0,
from jni/../../Classes/patmgr.h:4,
from jni/../../Classes/patmgr.cpp:1: jni/../../Classes/helpertypes.h: In instantiation of 'std::string
mx::to_string(const T&) [with T = unsigned int; std::string =
std::basic_string]':
jni/../../Classes/utilities/pattern/pat_bit_spec.h:185:37: required
from here jni/../../Classes/helpertypes.h:94:22: error: call of
overloaded 'operator<<(std::ostringstream&, const unsigned int&)' is
ambiguous ::operator<<(os, val);
^ jni/../../Classes/helpertypes.h:94:22: note: candidates are: In file included from
jni/../../Classes/utilities/pattern/pat.h:3:0,
from jni/../../Classes/patmgr.h:4,
from jni/../../Classes/patmgr.cpp:1: jni/../../Classes/utilities/pattern/abspat.h:72:22: note:
std::ostream& operator<<(std::ostream&, AbsPat::Loc)
inline std::ostream& operator<<(std::ostream& os, AbsPat::Loc loc)
^ jni/../../Classes/utilities/pattern/abspat.h:72:22: note: no known
conversion for argument 2 from 'const unsigned int' to 'AbsPat::Loc'
在这个细分市场中:
错误:重载 'operator<<(std::ostringstream&, const unsigned int&)' 的调用不明确
::运算符<<(os, val);
^
这怎么会模棱两可?
出于某种原因,编译器认为它不会再考虑我在全局命名空间中定义的重载。然后我尝试在与朋友相同的命名空间中定义重载,但后来我遇到了这些歧义错误。出现歧义错误是因为我留下了重载的前向声明,就好像它是在全局命名空间而不是 mx:: 命名空间中定义的一样。一旦我删除了前向声明并让编译器利用 ADL 的强大功能,看在上帝的份上它编译了。
为什么在全局命名空间中查找重载失败(以及为什么只在一个编译单元中)对我来说仍然是一个长期的谜。
故事的寓意:
从现在开始,我只会在 class 所在的同一名称空间中声明运算符重载。
注意:我以前没有遇到过这个问题!我的 to_string 方法工作得很好,模板实例化为我的 Point class 找到了正确的重载,我已经使用它几个月了!但是最后一次提交出了点问题,在一个源文件中我收到了这个 well-known 错误消息(仅在这个源文件中,在其他地方 mx::to_string(mx::Point) 可以正常工作) .我无法弄清楚可能是什么原因,因为我没有注意到任何可能搞砸的线路。
Plus 把流运算符重载的相关问题都扫了一遍,没找到解决办法。
所以我有一个观点class:
#ifndef MXBASIC_UTILITIES_H
#define MXBASIC_UTILITIES_H
#include <ostream>
#include <string>
namespace mx{
class Point;
}
class mx::Point
{
public:
Point();
Point(int x, int y);
int getX() const;
int getY() const;
int& getX();
int& getY();
//...
};
inline mx::Point::Point() : _x(0), _y(0) {}
inline mx::Point::Point(int x, int y) : _x(x), _y(y) {}
inline int mx::Point::getX() const { return _x; }
inline int mx::Point::getY() const { return _y; }
inline int& mx::Point::getX() { return _x; }
inline int& mx::Point::getY() { return _y; }
// THE OVERLOAD:
inline std::ostream& operator<<(std::ostream& os, const mx::Point& point){
return os << '(' << point.getX() << ',' << point.getY() << ')';
}
#endif
一个名为 header 的 helpertypes.h 文件,其中我有 to_string 函数:
#ifndef HELPERTYPES_H
#define HELPERTYPES_H
#include <iostream>
#include <cstdint>
#include <memory>
#include <sstream>
#include <string>
// ...
namespace mx{
template<typename T>
std::string to_string(const T& val)
{
std::ostringstream os;
os.flags(std::ios::fixed);
os.precision(2);
os << val; // getting error here as of recently, both in MinGW 4.7.3 and MSVC15
return os.str();
}
}
#endif
完整的错误信息: 此处更具可读性:pastebin.com/gFdFezrV
MSVC15:
2>c:(...)\classes\helpertypes.h(87): error C2679: binary '<<': no operator found which takes a right-hand operand of type 'const mx::Point' (or there is no acceptable conversion) 2> c:\program files (x86)\microsoft visual studio 14.0\vc\include\ostream(495): note: could be 'std::basic_ostream> &std::basic_ostream>::operator <<(std::basic_streambuf> *)' 2> c:\program files (x86)\microsoft visual studio 14.0\vc\include\ostream(475): note: or 'std::basic_ostream> &std::basic_ostream>::operator <<(const void *)' 2> c:\program files (x86)\microsoft visual studio 14.0\vc\include\ostream(455): note: or 'std::basic_ostream> &std::basic_ostream>::operator <<(long double)' 2> c:\program files (x86)\microsoft visual studio 14.0\vc\include\ostream(435): note: or 'std::basic_ostream> &std::basic_ostream>::operator <<(double)' 2> c:\program files (x86)\microsoft visual studio 14.0\vc\include\ostream(415): note: or 'std::basic_ostream> &std::basic_ostream>::operator <<(float)' 2> c:\program files (x86)\microsoft visual studio 14.0\vc\include\ostream(395): note: or 'std::basic_ostream> &std::basic_ostream>::operator <<(unsigned __int64)' 2> c:\program files (x86)\microsoft visual studio 14.0\vc\include\ostream(375): note: or 'std::basic_ostream> &std::basic_ostream>::operator <<(__int64)' 2> c:\program files (x86)\microsoft visual studio 14.0\vc\include\ostream(355): note: or 'std::basic_ostream> &std::basic_ostream>::operator <<(unsigned long)' 2> c:\program files (x86)\microsoft visual studio 14.0\vc\include\ostream(335): note: or 'std::basic_ostream> &std::basic_ostream>::operator <<(long)' 2> c:\program files (x86)\microsoft visual studio 14.0\vc\include\ostream(315): note: or 'std::basic_ostream> &std::basic_ostream>::operator <<(unsigned int)' 2> c:\program files (x86)\microsoft visual studio 14.0\vc\include\ostream(290): note: or 'std::basic_ostream> &std::basic_ostream>::operator <<(int)' 2> c:\program files (x86)\microsoft visual studio 14.0\vc\include\ostream(270): note: or 'std::basic_ostream> &std::basic_ostream>::operator <<(unsigned short)' 2> c:\program files (x86)\microsoft visual studio 14.0\vc\include\ostream(236): note: or 'std::basic_ostream> &std::basic_ostream>::operator <<(short)' 2> c:\program files (x86)\microsoft visual studio 14.0\vc\include\ostream(216): note: or 'std::basic_ostream> &std::basic_ostream>::operator <<(bool)' 2> c:\program files (x86)\microsoft visual studio 14.0\vc\include\ostream(209): note: or 'std::basic_ostream> &std::basic_ostream>::operator <<(std::ios_base &(__cdecl *)(std::ios_base &))' 2> c:\program files (x86)\microsoft visual studio 14.0\vc\include\ostream(202): note: or
'std::basic_ostream> &std::basic_ostream>::operator <<(std::basic_ios> &(__cdecl *)(std::basic_ios> &))' 2> c:\program files (x86)\microsoft visual studio 14.0\vc\include\ostream(196): note: or 'std::basic_ostream> &std::basic_ostream>::operator <<(std::basic_ostream> &(__cdecl *)(std::basic_ostream> &))' 2> c:\program files (x86)\microsoft visual studio 14.0\vc\include\ostream(692): note: or 'std::basic_ostream> &std::operator <<>(std::basic_ostream> &,const char *)' 2> c:\program files (x86)\microsoft visual studio 14.0\vc\include\ostream(739): note: or 'std::basic_ostream> &std::operator <<>(std::basic_ostream> &,char)' 2> c:\program files (x86)\microsoft visual studio 14.0\vc\include\ostream(777): note: or 'std::basic_ostream> &std::operator <<>(std::basic_ostream> &,const char *)' 2> c:\program files (x86)\microsoft visual studio 14.0\vc\include\ostream(824): note: or 'std::basic_ostream> &std::operator <<>(std::basic_ostream> &,char)' 2> c:\program files (x86)\microsoft visual studio 14.0\vc\include\ostream(950): note: or 'std::basic_ostream> &std::operator <<>(std::basic_ostream> &,const signed char *)' 2> c:\program files (x86)\microsoft visual studio 14.0\vc\include\ostream(957): note: or
'std::basic_ostream> &std::operator <<>(std::basic_ostream> &,signed char)' 2> c:\program files (x86)\microsoft visual studio 14.0\vc\include\ostream(964): note: or 'std::basic_ostream> &std::operator <<>(std::basic_ostream> &,const unsigned char *)' 2> c:\program files (x86)\microsoft visual studio 14.0\vc\include\ostream(971): note: or
'std::basic_ostream> &std::operator <<>(std::basic_ostream> &,unsigned char)' 2> c:\program files (x86)\microsoft visual studio 14.0\vc\include\ostream(981): note: or 'std::basic_ostream> &std::operator <<,mx::Point>(std::basic_ostream> &&,const _Ty &)' 2> with 2> [ 2>
_Ty=mx::Point 2> ] 2> c:\program files (x86)\microsoft visual studio 14.0\vc\include\ostream(1019): note: or
'std::basic_ostream> &std::operator <<>(std::basic_ostream> &,const std::error_code &)' 2> c:\program files (x86)\microsoft visual studio 14.0\vc\include\random(2568): note: or
'std::basic_ostream> &std::operator <<>(std::basic_ostream> &,const std::bernoulli_distribution &)' 2> c:\program files (x86)\microsoft visual studio 14.0\vc\include\thread(246): note: or
'std::basic_ostream> &std::operator <<>(std::basic_ostream> &,std::thread::id)' 2> c:(...)\classes\helpertypes.h(87): note: while trying to match the argument list '(std::ostringstream, const mx::Point)' 2> c:(...)\classes(...)\entity\tinyent\tinyent.cpp(1502): note: see reference to function template instantiation 'std::string mx::to_string(const T &)' being compiled 2> with 2> [ 2> T=mx::Point 2> ]MinGW 4.7.3:
In file included from jni/../../Classes/utilities/pattern/pat.h:5:0, from jni/../../Classes/(...)/entity/tinyent/../ent.h:3, from jni/../../Classes/(...)/entity/tinyent/tinyent.h:2, from jni/../../Classes/(...)/entity/tinyent/tinyent.cpp:1: jni/../../Classes/helpertypes.h: In instantiation of 'std::string mx::to_string(const T&) [with T = mx::Point; std::string = std::basic_string]': jni/../../Classes/(...)/entity/tinyent/tinyent.cpp:1502:20: required from here jni/../../Classes/helpertypes.h:87:5: error: cannot bind 'std::basic_ostream' lvalue to 'std::basic_ostream&&' os << val; ^ In file included from jni/../../Classes/utilities/pattern/abspat.h:6:0, from jni/../../Classes/utilities/pattern/pat.h:3, from jni/../../Classes/(...)/entity/tinyent/../ent.h:3, from jni/../../Classes/(...)/entity/tinyent/tinyent.h:2, from jni/../../Classes/(...)/entity/tinyent/tinyent.cpp:1: C:/Users/(...)/Documents/libs/android-ndk-r10e/sources/cxx-stl/gnu-libstdc++/4.9/include/ostream:602:5: note: initializing argument 1 of 'std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits; _Tp = mx::Point]' operator<<(basic_ostream<_CharT, _Traits>&& __os, const _Tp& __x) ^
触发实例化的地方:
tinyent.h
#pragma once
#include <string>
#include "ent.h"
#include "mxbasic_utilities.h" // definition of my overload included!
class TinyEnt : public Ent
{
public:
// ...
virtual std::string toString() const override;
private:
// ...
int _posX, posY;
};
tinyent.cpp
#include "tinyent.h"
// ...
std::string toString() const
{
return std::string("TinyEnt ") + mx::to_string(id()) + " at " // decltype(id()) is ULL, no problem here
+ mx::to_string(mx::Point(_posX, _posY)); // place of instantiation, overload not found
}
如果我将我的 to_string 函数的定义放在这个 toString 函数的前面,它就可以工作:
备选tinyent.cpp
#include "tinyent.h"
template<typename T>
std::string to_string(const T& val)
{
std::ostringstream os;
os.flags(std::ios::fixed);
os.precision(2);
os << val;
return os.str();
}
std::string toString() const
{
return std::string("TinyEnt ") + mx::to_string(id()) + " at "
+ ::to_string(mx::Point(_posX, _posY)); // no problems this way
}
我完全不知道该怎么办。我检查了包括 层次结构如果可能有递归包含,则没有(helpertypes.h 仅取决于 stl headers)。我试过从 ground 0 重建,并尝试使用不同的编译器。您有任何提示可能出了什么问题吗?
编辑:
在我的 mx::to_string 函数中使用完整命名空间限定时(例如:::operator(os, val);
),我收到不同的错误消息。当输入 size_t(在本例中为 unsigned int)时,实例化会引发歧义错误,就好像在第一轮参数查找中找不到它一样。
In file included from jni/../../Classes/utilities/pattern/pat.h:5:0, from jni/../../Classes/patmgr.h:4, from jni/../../Classes/patmgr.cpp:1: jni/../../Classes/helpertypes.h: In instantiation of 'std::string mx::to_string(const T&) [with T = unsigned int; std::string = std::basic_string]': jni/../../Classes/utilities/pattern/pat_bit_spec.h:185:37: required from here jni/../../Classes/helpertypes.h:94:22: error: call of overloaded 'operator<<(std::ostringstream&, const unsigned int&)' is ambiguous ::operator<<(os, val); ^ jni/../../Classes/helpertypes.h:94:22: note: candidates are: In file included from jni/../../Classes/utilities/pattern/pat.h:3:0, from jni/../../Classes/patmgr.h:4, from jni/../../Classes/patmgr.cpp:1: jni/../../Classes/utilities/pattern/abspat.h:72:22: note: std::ostream& operator<<(std::ostream&, AbsPat::Loc) inline std::ostream& operator<<(std::ostream& os, AbsPat::Loc loc) ^ jni/../../Classes/utilities/pattern/abspat.h:72:22: note: no known conversion for argument 2 from 'const unsigned int' to 'AbsPat::Loc'
在这个细分市场中: 错误:重载 'operator<<(std::ostringstream&, const unsigned int&)' 的调用不明确 ::运算符<<(os, val); ^ 这怎么会模棱两可?
出于某种原因,编译器认为它不会再考虑我在全局命名空间中定义的重载。然后我尝试在与朋友相同的命名空间中定义重载,但后来我遇到了这些歧义错误。出现歧义错误是因为我留下了重载的前向声明,就好像它是在全局命名空间而不是 mx:: 命名空间中定义的一样。一旦我删除了前向声明并让编译器利用 ADL 的强大功能,看在上帝的份上它编译了。
为什么在全局命名空间中查找重载失败(以及为什么只在一个编译单元中)对我来说仍然是一个长期的谜。
故事的寓意: 从现在开始,我只会在 class 所在的同一名称空间中声明运算符重载。