1 분 소요

개요

기존에는 암시적으로 형변환 되는 문제점이 있으니 형변환 연산자를 정의하지 말라고 했는데요(형변환 연산자 정의안전하지 않은 bool 형변환 연산자 정의 참고),

C++11 부터는 explicit 형변환 연산자를 추가하여 명시적으로만 형변환 할 수 있게 했습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class T {
public:
    // 암시적 형변환이 됩니다.
    operator bool() const {return true;}
};

class T_11 {
public:
    // 명시적으로만 형변환 됩니다.
    explicit operator bool() const {return true;} 
};

T t;
int val1{t}; // (△) 비권장. bool()을 이용하여 형변환 하고 암시적으로 int로 변환합니다.

T_11 t_11;
// int val2{t_11}; // (X) 컴파일 오류
bool val3{static_cast<bool>(t_11)}; // 명시적으로 변환해야 사용할 수 있습니다.

안전한 bool 형변환

안전하지 않은 bool 형변환 연산자 정의에서, bool은 암시적으로 int로 형변환되면서 뜻하지 않은 동작을 할 수 있으니, bool 형변환을 정의하지 말라고 했는데요, explicit를 이용하여 이러한 문제를 차단할 수 있습니다.

단, explicit를 사용하더라도 if의 조건식에서는 암시적으로 bool로 변환되어 개체 유효성 평가에 사용할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class T_11 {
public:
    explicit operator bool() const {return true;}
};

T_11 t;
bool status = t; // (X) 컴파일 오류. explicit이므로 암시적 형변환이 되지 않습니다.

if (t) { // if 문에서는 bool로 형변환 됩니다. 개체 유효성 평가에 유용합니다.
    EXPECT_TRUE(true);
}
else {
    EXPECT_TRUE(false);
}

(C++20~) explicit(bool)

기존에는 암시적 형변환을 막기 위해서 explicit를 사용했습니다. explicit는 모든 타입에 대해서 암시적 형변환을 차단하는데요(explicit 참고),

1
2
3
4
5
6
7
8
9
10
11
12
template<typename T>
class A {
    T m_Val;
public:
    explicit A(T val) : m_Val{val} {} // 모든 타입에 대해 암시적 형변환을 차단합니다.
};

A<int> a{0};
A<int> b = 0; // (X) 컴파일 오류. explicit로 차단했습니다.

A<std::string> c{"Hello"};
A<std::string> d = std::string{"World"}; // (X) 컴파일 오류. explicit로 차단했습니다.

C++20 부터는 explicit(bool)이 추가되어 특정 조건일 때만 explicit로 동작하게 할 수 있습니다.

다음 예는 int 타입인 경우에만 explicit로 동작하고, 그외 타입은 암시적으로 형변환됩니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
template<typename T>
class A_20 {
    T m_Val;
public:
    // 정수 타입인 경우만 explicit 입니다.
    explicit(std::is_integral<T>::value) A_20(T val) : m_Val{val} {}
};

A_20<int> a{0};
A_20<int> b = 0; // (X) 컴파일 오류. explicit로 차단했습니다.

A_20<std::string> c{"Hello"};
A_20<std::string> d = std::string{"World"}; // (O) 정수 타입이 아니어서 암시적 형변환을 허용합니다.       

태그:

카테고리:

업데이트:

댓글남기기