Development Tip

연산자 <<는 정확히 하나의 인수를 가져야합니다.

yourdevel 2020. 10. 9. 12:28
반응형

연산자 <<는 정확히 하나의 인수를 가져야합니다.


#include "logic.h"
...

class A
{
friend ostream& operator<<(ostream&, A&);
...
};

logic.cpp

#include "a.h"
...
ostream& logic::operator<<(ostream& os, A& a)
{
...
}
...

컴파일하면 다음과 같이 표시됩니다.

std :: ostream & logic :: operator << (std :: ostream &, A &) '는 정확히 하나의 인수를 가져야합니다.

무엇이 문제입니까?


문제는 클래스 내부에서 정의한다는 것입니다.

a) 두 번째 인수가 암시 적 ()임을 의미 this하고

b) 원하는 것을 수행하지 않습니다 std::ostream.

자유 함수로 정의해야합니다.

class A { /* ... */ };
std::ostream& operator<<(std::ostream&, const A& a);

친구 함수는 멤버 함수가 아니므로 문제는 다음 operator<<의 친구로 선언한다는 것 입니다 A.

 friend ostream& operator<<(ostream&, A&);

그런 다음 클래스의 멤버 함수로 정의하십시오. logic

 ostream& logic::operator<<(ostream& os, A& a)
          ^^^^^^^

logic클래스인지 네임 스페이스 인지 혼란 스럽 습니까?

오류는 operator<<두 개의 인수 를 사용하는 멤버를 정의하려고했기 때문에 암시 적 this매개 변수를 포함하여 세 개의 인수가 필요 합니다. 연산자는 두 개의 인수 만 사용할 수 있으므로 작성 a << b시 두 개의 인수는 ab입니다.

당신은 정의 할 ostream& operator<<(ostream&, const A&)A와 - 구성원 기능, 확실히의 구성원으로 logic는 그 클래스와는 아무 상관이 없기 때문에!

std::ostream& operator<<(std::ostream& os, const A& a)
{
  return os << a.number;
}

템플릿 클래스에서이 문제가 발생했습니다. 다음은 내가 사용해야하는보다 일반적인 솔루션입니다.

template class <T>
class myClass
{
    int myField;

    // Helper function accessing my fields
    void toString(std::ostream&) const;

    // Friend means operator<< can use private variables
    // It needs to be declared as a template, but T is taken
    template <class U>
    friend std::ostream& operator<<(std::ostream&, const myClass<U> &);
}

// Operator is a non-member and global, so it's not myClass<U>::operator<<()
// Because of how C++ implements templates the function must be
// fully declared in the header for the linker to resolve it :(
template <class U>
std::ostream& operator<<(std::ostream& os, const myClass<U> & obj)
{
  obj.toString(os);
  return os;
}

이제 : * 내 toString () 함수가 cpp에 들어가면 인라인 될 수 없습니다. * 헤더에 일부 코드가 붙어있어 제거 할 수 없습니다. * 연산자는 인라인되지 않은 toString () 메서드를 호출합니다.

operator <<의 본문은 friend 절 또는 클래스 외부에서 선언 할 수 있습니다. 두 옵션 모두 추악합니다. :(

아마도 내가 오해하거나 뭔가 빠졌을 수도 있지만 연산자 템플릿을 앞으로 선언하는 것은 gcc에서 링크되지 않습니다.

이것도 작동합니다.

template class <T>
class myClass
{
    int myField;

    // Helper function accessing my fields
    void toString(std::ostream&) const;

    // For some reason this requires using T, and not U as above
    friend std::ostream& operator<<(std::ostream&, const myClass<T> &)
    {
        obj.toString(os);
        return os;
    }
}

operator <<를 구현하기 위해 템플릿 화되지 않은 부모 클래스를 사용하고 가상 toString () 메서드를 사용하면 헤더에서 선언을 강제하는 템플릿 문제를 피할 수 있다고 생각합니다.


operator<<멤버 함수로 정의 하면 비 멤버를 사용한 경우와는 다른 분해 구문을 갖게됩니다 operator<<. 비 멤버 operator<<는 멤버 operator<<가 단항 연산자 인 이항 연산자입니다.

// Declarations
struct MyObj;
std::ostream& operator<<(std::ostream& os, const MyObj& myObj);

struct MyObj
{
    // This is a member unary-operator, hence one argument
    MyObj& operator<<(std::ostream& os) { os << *this; return *this; }

    int value = 8;
};

// This is a non-member binary-operator, 2 arguments
std::ostream& operator<<(std::ostream& os, const MyObj& myObj)
{
    return os << myObj.value;
}

So.... how do you really call them? Operators are odd in some ways, I'll challenge you to write the operator<<(...) syntax in your head to make things make sense.

MyObj mo;

// Calling the unary operator
mo << std::cout;

// which decomposes to...
mo.operator<<(std::cout);

Or you could attempt to call the non-member binary operator:

MyObj mo;

// Calling the binary operator
std::cout << mo;

// which decomposes to...
operator<<(std::cout, mo);

You have no obligation to make these operators behave intuitively when you make them into member functions, you could define operator<<(int) to left shift some member variable if you wanted to, understand that people may be a bit caught off guard, no matter how many comments you may write.

Almost lastly, there may be times where both decompositions for an operator call are valid, you may get into trouble here and we'll defer that conversation.

Lastly, note how odd it might be to write a unary member operator that is supposed to look like a binary operator (as you can make member operators virtual..... also attempting to not devolve and run down this path....)

struct MyObj
{
    // Note that we now return the ostream
    std::ostream& operator<<(std::ostream& os) { os << *this; return os; }

    int value = 8;
};

This syntax will irritate many coders now....

MyObj mo;

mo << std::cout << "Words words words";

// this decomposes to...
mo.operator<<(std::cout) << "Words words words";

// ... or even further ...
operator<<(mo.operator<<(std::cout), "Words words words");

Note how the cout is the second argument in the chain here.... odd right?

참고URL : https://stackoverflow.com/questions/10744787/operator-must-take-exactly-one-argument

반응형