User-defined conversion function
암시적 변환 또는 명시적 변환 을 통해 클래스 타입 에서 다른 타입으로의 변환을 가능하게 합니다.
목차 |
구문
변환 함수는 다음과 같은 형태의 이름을 가진, 매개변수가 없고 명시적 반환 타입이 없으며, 비정적 멤버 함수 또는 멤버 함수 템플릿 처럼 선언됩니다:
operator
conversion-type-id
|
(1) | ||||||||
explicit
operator
conversion-type-id
|
(2) | (C++11부터) | |||||||
explicit (
expression
)
operator
conversion-type-id
|
(3) | (C++20부터) | |||||||
conversion-type-id
는
type-id
이지만, 함수 및 배열 연산자
[]
또는
()
가 그 선언자에서 허용되지 않습니다(따라서 배열에 대한 포인터와 같은 타입으로의 변환은 타입 별칭/typedef 또는 identity 템플릿이 필요합니다: 아래 참조). typedef와 관계없이,
conversion-type-id
는 배열 또는 함수 타입을 나타낼 수 없습니다.
사용자 정의 변환 함수의 선언에서는 반환 타입이 허용되지 않지만,
decl-specifier-seq
는
선언 문법
에 존재할 수 있으며
type-specifier
또는
static
키워드를 제외한 모든 지정자를 포함할 수 있습니다. 특히,
explicit
외에도
inline
,
virtual
,
constexpr
(C++11부터)
,
consteval
(C++20부터)
, 그리고
friend
지정자도 허용됩니다 (단,
friend
는 한정된 이름이 필요함:
friend
A
::
operator
B
(
)
;
).
이러한 멤버 함수가 클래스 X 내에서 선언될 때, X에서 conversion-type-id 로의 변환을 수행합니다:
struct X { // 암시적 변환 operator int() const { return 7; } // 명시적 변환 explicit operator int*() const { return nullptr; } // 오류: 변환 타입 ID에서 배열 연산자는 허용되지 않음 // operator int(*)[3]() const { return nullptr; } using arr_t = int[3]; operator arr_t*() const { return nullptr; } // typedef를 통한 경우 OK // operator arr_t () const; // 오류: 어떤 경우에도 배열로의 변환은 허용되지 않음 }; int main() { X x; int n = static_cast<int>(x); // OK: n을 7로 설정 int m = x; // OK: m을 7로 설정 int* p = static_cast<int*>(x); // OK: p를 null로 설정 // int* q = x; // 오류: 암시적 변환 없음 int (*pa)[3] = x; // OK }
설명
사용자 정의 변환 함수는 implicit conversion 의 두 번째 단계에서 호출되며, 이는 0개 또는 1개의 converting constructor 또는 0개 또는 1개의 사용자 정의 변환 함수로 구성됩니다.
변환 함수와 변환 생성자 모두 일부 사용자 정의 변환을 수행하는 데 사용될 수 있는 경우, 변환 함수와 생성자는 오버로드 해결 에서 복사 초기화 와 참조 초기화 상황에서 모두 고려되지만, 직접 초기화 상황에서는 생성자만 고려됩니다.
struct To { To() = default; To(const struct From&) {} // 변환 생성자 }; struct From { operator To() const {return To();} // 변환 함수 }; int main() { From f; To t1(f); // 직접 초기화: 생성자 호출 // 참고: 변환 생성자를 사용할 수 없는 경우, 암시적 복사 생성자가 // 선택되고 인자를 준비하기 위해 변환 함수가 호출됨 // To t2 = f; // 복사 초기화: 모호함 // 참고: 변환 함수가 비 const 타입에서 온 경우, 예를 들어 // From::operator To();, 이 경우 생성자 대신 선택됨 To t3 = static_cast<To>(f); // 직접 초기화: 생성자 호출 const To& r = f; // 참조 초기화: 모호함 }
자신의 (cv 한정자가 있을 수 있는) 클래스로(또는 그에 대한 참조로), 자신의 클래스의 기저 클래스로(또는 그에 대한 참조로), 그리고 void 타입으로의 변환 함수는 정의할 수 있지만, 변환 시퀀스의 일부로 실행될 수 없습니다. 단, 일부 경우 virtual dispatch를 통한 경우는 예외입니다:
struct D; struct B { virtual operator D() = 0; }; struct D : B { operator D() override { return D(); } }; int main() { D obj; D obj2 = obj; // D::operator D()를 호출하지 않음 B& br = obj; D obj3 = br; // 가상 디스패치를 통해 D::operator D() 호출 }
멤버 함수 호출 구문을 사용하여 호출할 수도 있습니다:
struct B {}; struct X : B { operator B&() { return *this; }; }; int main() { X x; B& b1 = x; // X::operatorB&()를 호출하지 않음 B& b2 = static_cast<B&>(x); // X::operatorB&를 호출하지 않음 B& b3 = x.operator B&(); // X::operatorB&를 호출함 }
변환 함수에 대한 명시적 호출을 수행할 때, conversion-type-id 는 탐욕적(greedy)입니다: 이것은 가능한 conversion-type-id 를 형성할 수 있는 가장 긴 토큰 시퀀스입니다 (속성이 있는 경우 포함) (C++11부터) :
& x.operator int * a; // 오류: & (x.operator int*) a로 파싱됨, // & (x.operator int) * a로 파싱되지 않음 operator int [[noreturn]] (); // 오류: noreturn 속성이 타입에 적용됨
|
자리 표시자 auto 는 conversion-type-id 에서 사용될 수 있으며, 추론된 반환 타입 을 나타냅니다: struct X { operator int(); // OK operator auto() -> short; // error: trailing return type not part of syntax operator auto() const { return 10; } // OK: deduced return type operator decltype(auto)() const { return 10l; } // OK: deduced return type }; 참고: 변환 함수 템플릿 은 추론된 반환 타입을 가질 수 없습니다. |
(C++14부터) |
변환 함수는 상속될 수 있으며 virtual 일 수 있지만 static 일 수는 없습니다. 파생 클래스의 변환 함수는 동일한 타입으로 변환하는 경우가 아니면 기본 클래스의 변환 함수를 가리지 않습니다.
변환 함수는 템플릿 멤버 함수일 수 있습니다, 예를 들어,
std::auto_ptr<T>::operator auto_ptr<Y>
. 적용 가능한 특별 규칙에 대해서는
멤버 템플릿
과
템플릿 인자 추론
을 참조하십시오.
키워드
결함 보고서
다음의 동작 변경 결함 보고서들은 이전에 발표된 C++ 표준에 소급 적용되었습니다.
| DR | 적용 대상 | 게시된 동작 | 올바른 동작 |
|---|---|---|---|
| CWG 296 | C++98 | 변환 함수가 static일 수 있었음 | static으로 선언될 수 없음 |
| CWG 2016 | C++98 |
변환 함수가 반환 타입을 지정할 수 없었으나,
해당 타입들은 conversion-type-id 에 존재함 |
변환 함수의 선언 지정자에서
반환 타입을 지정할 수 없음 |
| CWG 2175 | C++11 |
[
[
noreturn
]
]
가
operator int [ [ noreturn ] ] ( ) ; 에서 noptr-declarator (함수 선언자)의 일부로 파싱되는지 아니면 conversion-type-id 의 일부로 파싱되는지 불명확했음 |
해당 구문은
conversion-type-id 의 일부로 파싱됨 |