Namespaces
Variants

User-defined conversion function

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

암시적 변환 또는 명시적 변환 을 통해 클래스 타입 에서 다른 타입으로의 변환을 가능하게 합니다.

목차

구문

변환 함수는 다음과 같은 형태의 이름을 가진, 매개변수가 없고 명시적 반환 타입이 없으며, 비정적 멤버 함수 또는 멤버 함수 템플릿 처럼 선언됩니다:

operator conversion-type-id (1)
explicit operator conversion-type-id (2) (C++11부터)
explicit ( expression ) operator conversion-type-id (3) (C++20부터)
1) 모든 암시적 변환 명시적 변환 에 참여하는 사용자 정의 변환 함수를 선언합니다.
2) 직접 초기화 명시적 변환 에만 참여하는 사용자 정의 변환 함수를 선언합니다.
3) 조건부 explicit 사용자 정의 변환 함수를 선언합니다.

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> . 적용 가능한 특별 규칙에 대해서는 멤버 템플릿 템플릿 인자 추론 을 참조하십시오.

키워드

operator

결함 보고서

다음의 동작 변경 결함 보고서들은 이전에 발표된 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 의 일부로 파싱됨