템플릿 클래스에 대해 friend operator << 오버로딩
현재 StackOverflow.com에서 내 문제에 관한 몇 가지 질문을 읽었으며 어느 것도 내 문제를 해결하지 못하는 것 같습니다. 또는 내가 잘못했을 수도 있습니다 <<
. 인라인 함수로 만들면 과부하가 작동합니다. 그러나 내 경우에는 어떻게 작동합니까?
warning: friend declaration std::ostream& operator<<(std::ostream&, const D<classT>&)' declares a non-template function
warning: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here) -Wno-non-template-friend disables this warning
/tmp/cc6VTWdv.o:uppgift4.cc:(.text+0x180): undefined reference to operator<<(std::basic_ostream<char, std::char_traits<char> >&, D<int> const&)' collect2: ld returned 1 exit status
코드:
template <class T>
T my_max(T a, T b)
{
if(a > b)
return a;
else
return b;
}
template <class classT>
class D
{
public:
D(classT in)
: d(in) {};
bool operator>(const D& rhs) const;
classT operator=(const D<classT>& rhs);
friend ostream& operator<< (ostream & os, const D<classT>& rhs);
private:
classT d;
};
int main()
{
int i1 = 1;
int i2 = 2;
D<int> d1(i1);
D<int> d2(i2);
cout << my_max(d1,d2) << endl;
return 0;
}
template <class classT>
ostream& operator<<(ostream &os, const D<classT>& rhs)
{
os << rhs.d;
return os;
}
이것은 비슷하지만 실제로는 같지는 않은 다른 접근 방식을 가진 자주 묻는 질문 중 하나입니다. 세 가지 접근 방식은 함수의 친구라고 선언하는 사람과이를 구현하는 방법에 따라 다릅니다.
외향적 인
템플릿의 모든 인스턴스화를 친구로 선언합니다. 이것은 당신이 대답으로 받아 들인 것이고 다른 대답의 대부분이 제안하는 것입니다. 이 접근 방식에서는 D<T>
친구에게 모든 operator<<
인스턴스화 를 선언 하여 특정 인스턴스화 를 불필요하게 엽니 다 . 즉,의 std::ostream& operator<<( std::ostream &, const D<int>& )
모든 내부에 액세스 할 수 D<double>
있습니다.
template <typename T>
class Test {
template <typename U> // all instantiations of this template are my friends
friend std::ostream& operator<<( std::ostream&, const Test<U>& );
};
template <typename T>
std::ostream& operator<<( std::ostream& o, const Test<T>& ) {
// Can access all Test<int>, Test<double>... regardless of what T is
}
내향적인 사람들
삽입 연산자의 특정 인스턴스화 만 친구로 선언하십시오. D<int>
삽입 연산자를 자신에게 적용하면 좋아할 수 있지만 std::ostream& operator<<( std::ostream&, const D<double>& )
.
이것은 두 가지 방법으로 수행 할 수 있습니다. @Emery Berger가 제안한 간단한 방법은 연산자를 인라인하는 것입니다. 이는 다른 이유로도 좋은 생각입니다.
template <typename T>
class Test {
friend std::ostream& operator<<( std::ostream& o, const Test& t ) {
// can access the enclosing Test. If T is int, it cannot access Test<double>
}
};
이 첫 번째 버전에서는되어 있지 A는 템플릿 생성 operator<<
, 오히려 각 인스턴스에 대한 비 템플릿 기능 Test
템플릿입니다. 다시 말하지만, 차이는 미묘하지만 이것은 기본적으로 수동으로 추가하는 것과 같습니다 std::ostream& operator<<( std::ostream&, const Test<int>& )
인스턴스화 할 때 Test<int>
, 그리고 다른 유사한 과부하는 인스턴스화하는 경우 Test
에 double
, 또는 다른 유형.
세 번째 버전은 더 번거 롭습니다. 코드를 인라인하지 않고 템플릿을 사용하면 다른 모든 인스턴스화 를 열지 않고도 템플릿의 단일 인스턴스화를 클래스의 친구로 선언 할 수 있습니다 .
// Forward declare both templates:
template <typename T> class Test;
template <typename T> std::ostream& operator<<( std::ostream&, const Test<T>& );
// Declare the actual templates:
template <typename T>
class Test {
friend std::ostream& operator<< <T>( std::ostream&, const Test<T>& );
};
// Implement the operator
template <typename T>
std::ostream& operator<<( std::ostream& o, const Test<T>& t ) {
// Can only access Test<T> for the same T as is instantiating, that is:
// if T is int, this template cannot access Test<double>, Test<char> ...
}
외향적 인 것을 활용
이 세 번째 옵션과 첫 번째 옵션의 미묘한 차이는 다른 클래스에 얼마나 개방하고 있는지에 있습니다. 외향적 버전 에서 남용의 예는 내부에 접근하기를 원하고 다음과 같이하는 사람입니다.
namespace hacker {
struct unique {}; // Create a new unique type to avoid breaking ODR
template <>
std::ostream& operator<< <unique>( std::ostream&, const Test<unique>& )
{
// if Test<T> is an extrovert, I can access and modify *any* Test<T>!!!
// if Test<T> is an introvert, then I can only mess up with Test<unique>
// which is just not so much fun...
}
}
그런 친구는 선언 할 수 없으며 다른 템플릿 유형을 지정해야합니다.
template <typename SclassT>
friend ostream& operator<< (ostream & os, const D<SclassT>& rhs);
SclassT
그림자가되지 않도록 주의하십시오 classT
. 정의 할 때
template <typename SclassT>
ostream& operator<< (ostream & os, const D<SclassT>& rhs)
{
// body..
}
이것은 컴파일러 경고없이 나를 위해 일했습니다.
#include <iostream>
using namespace std;
template <class T>
T my_max(T a, T b)
{
if(a > b)
return a;
else
return b;
}
template <class classT>
class D
{
public:
D(classT in)
: d(in) {};
bool operator>(const D& rhs) const {
return (d > rhs.d);
}
classT operator=(const D<classT>& rhs);
friend ostream& operator<< (ostream & os, const D& rhs) {
os << rhs.d;
return os;
}
private:
classT d;
};
int main()
{
int i1 = 1;
int i2 = 2;
D<int> d1(i1);
D<int> d2(i2);
cout << my_max(d1,d2) << endl;
return 0;
}
여기 있습니다 :
#include <cstdlib>
#include <iostream>
using namespace std;
template <class T>
T my_max(T a, T b)
{
if(a > b)
return a;
else
return b;
}
template <class classT>
class D
{
public:
D(classT in)
: d(in) {};
bool operator>(const D& rhs) const { return d > rhs.d;};
classT operator=(const D<classT>& rhs);
template<class classT> friend ostream& operator<< (ostream & os, const D<classT>& rhs);
private:
classT d;
};
template<class classT> ostream& operator<<(ostream& os, class D<typename classT> const& rhs)
{
os << rhs.d;
return os;
}
int main()
{
int i1 = 1;
int i2 = 2;
D<int> d1(i1);
D<int> d2(i2);
cout << my_max(d1,d2) << endl;
return 0;
}
애초에 친구를 사귀지 말아야한다고 생각합니다.
다음과 같이 공용 메서드 호출 print를 만들 수 있습니다 (비 템플릿 클래스의 경우).
std::ostream& MyClass::print(std::ostream& os) const
{
os << "Private One" << privateOne_ << endl;
os << "Private Two" << privateTwo_ << endl;
os.flush();
return os;
}
그런 다음 클래스 외부 (동일한 네임 스페이스에 있음)
std::ostream& operator<<(std::ostream& os, const MyClass& myClass)
{
return myClass.print(os);
}
템플릿 클래스에서도 작동해야한다고 생각하지만 아직 테스트하지 않았습니다.
ReferenceURL : https://stackoverflow.com/questions/4660123/overloading-friend-operator-for-template-class
'developer tip' 카테고리의 다른 글
Angular의 서버에서 텍스트 / csv 콘텐츠를 파일로 다운로드 (0) | 2021.01.05 |
---|---|
Jenkins의 credentials.xml에서 암호 추출 (0) | 2021.01.05 |
드로어 블에 저장된 이미지의 URI 가져 오기 (0) | 2021.01.05 |
Android Studio에서 tcpip를 통해 adb를 사용 하시겠습니까? (0) | 2021.01.05 |
heroku django에서 _uuid_generate_random 이름을 가져올 수 없습니다. (0) | 2021.01.05 |