2016-06-01 8 views
1

참고 : 이전에는이 ​​문제가 없었습니다! 내 to_string 메서드가 제대로 작동했다. 템플릿 인스턴스화가 내 Point 클래스에 대한 적절한 오버로드를 발견했으며 몇 달 동안 사용 해왔다. 그러나 마지막 커밋에 뭔가 잘못되어 한 소스 파일에서이 잘 알려진 오류 메시지가 나타납니다 (이 소스 파일에서만, 다른 곳에서는 mx :: to_string (mx :: Point)가 오류없이 작동합니다). 나는 잠재적으로 망쳐 놓을 수있는 선을 발견하지 못했기 때문에 무엇이 그 이유 일 수 있었는지 알아낼 수 없었습니다.헤더 인스턴스간에 호출 할 때 템플릿 인스턴스화가 오버로드 된 스트림 연산자에 대한 인수 목록과 일치 할 수 없음

Plus는 해결 방법을 찾지 않고 스트림 연산자 오버로딩과 관련된 모든 관련 질문을 훑어 보았습니다.

#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 

전체 오류 메시지 : 여기 더 읽기 : 내 to_string 기능이

#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라는 이름의 헤더 파일 :

그래서 나는 점 클래스가 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) ^

인스턴스화 위치 riggered :

대체 :

내가 바로 작동이를 toString 기능을 앞에 내 to_string 함수의 정의를 넣으면

#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 
} 

tinyent.cpp

#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.h 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 헤더에만 의존합니다). 지상 0에서 재건을 시도하고 다른 컴파일러를 사용해 보았습니다. 무엇이 잘못되었을 수 있다는 힌트가 있습니까?

편집 : 내 MX :: to_string 기능 전체 네임 스페이스 자격을 사용하여 (그래서 같은 : ::operator(os, val);) 나는 다른 오류 메시지를 얻을. 이 인스턴스화는 size_t (이 경우 unsigned int)와 함께 제공 될 때 모호성 오류를 발생시킵니다. 마치 인수 조회의 첫 번째 라운드에서 찾지 못한 것입니다.

MSVC15MinGW에 의해 생성 된 오류 메시지. 이 분야에서

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'

: 오류 : 과부하 콜 '연산자 < < (표준 : ostringstream & const가 부호 & INT)가'모호한 :: 연산자 < < (OS, 발); ^ 어떻게 이것이 모호 할 수 있습니까?

+1

분명한 것은 : 당신의 helpertypes.h (여전히)는'operator <<'정의에 헤더 파일을 포함합니까? – Smeeheey

+0

또한'os << val' 행을 (완전히 네임 스페이스 한정)'ms :: operator << (os, val)'로 변경하여 문제가있는 곳에서 볼 수 있습니다. – Smeeheey

+0

helpertypes.h는 그렇지 않습니다. 오버로딩 된 연산자의 정의를 포함 할 필요가 있습니다. 즉, 인스턴스화 작업입니다. 정규화 된 네임 스페이스는 전역 함수이므로 :: operator << (os, val)이 될 것입니다. 그러나 연산자를 사용할 때 다른 오류 메시지가 나타납니다. – MatrixAndrew

답변

0

컴파일러는 몇 가지 이유로 글로벌 네임 스페이스에 정의 된 오버로드를 더 이상 고려하지 않을 것이라고 생각했습니다. 그런 다음 친구와 동일한 네임 스페이스에서 오버로드를 정의하려고 시도했지만 이러한 모호한 오류가 발생했습니다. 모호성 오류는 mx :: namespace가 아니라 전역 네임 스페이스에 정의 된 것처럼 과부하를 전달한 선언을 남겼 기 때문에 발생합니다. 일단 전방 선언을 제거하고 컴파일러가 ADL의 힘을 활용하게하면, 그것은 하나님을 위해서 컴파일됩니다.

글로벌 네임 스페이스에서 오버로드에 대한 조회가 왜 부러 졌는지 (그리고 왜 하나의 컴파일 단위에서만 이유가되는 것일까?) 아직도 내게는 오랜 미스테리입니다.

이야기의 도덕 : 나는 클래스가 지금부터와 동일한 네임 스페이스에서만 연산자 오버로드를 선언 할 것이다.