gpt4 book ai didi

c++ - 在 header 之间调用时,模板实例化无法匹配重载流运算符的参数列表

转载 作者:太空宇宙 更新时间:2023-11-04 13:15:32 24 4
gpt4 key购买 nike

注意:以前我没有遇到过这个问题!我的 to_string 方法工作得很好,模板实例化为我的 Point 类找到了正确的重载,我已经使用它几个月了!然而,最后一次提交出了点问题,在一个源文件中我收到了这个众所周知的错误消息(仅在这个源文件中,在其他地方 mx::to_string(mx::Point) 可以正常工作)。我无法弄清楚可能是什么原因,因为我没有注意到任何可能搞砸的线路。

Plus 遍历了所有关于流运算符重载的相关问题,但没有找到解决方案。

所以我有一个点类:

#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

一个名为 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 header )。我试过从 ground 0 重建,并尝试使用不同的编译器。您有任何提示可能出了什么问题吗?

编辑:在我的 mx::to_string 函数中使用完整命名空间限定时(例如:::operator(os, val);),我收到不同的错误消息。当输入 size_t(在本例中为 unsigned int)时,实例化会引发歧义错误,就好像在第一轮参数查找中找不到它一样。

MSVC15 产生的错误信息和 MinGW .

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); ^这怎么会模棱两可呢?

最佳答案

出于某种原因,编译器认为它不会再考虑我在全局命名空间中定义的重载。然后我尝试在与 friend 相同的命名空间中定义重载,但后来我遇到了这些歧义错误。出现歧义错误是因为我留下了重载的前向声明,就好像它是在全局命名空间而不是 mx::命名空间中定义的一样。一旦我删除了前向声明并让编译器利用 ADL 的强大功能,看在上帝的份上它就编译好了。

为什么在全局命名空间中查找重载失败(以及为什么只在一个编译单元中)对我来说仍然是一个长期的谜。

故事的寓意:从现在开始,我将只在类所在的同一命名空间中声明运算符重载。

关于c++ - 在 header 之间调用时,模板实例化无法匹配重载流运算符的参数列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37562333/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com