2 min read

C++ 복사 연산자에 template 사용하기

퍼펙트 포워딩을 하기위해 복사연산자에 template을 사용할려고 아래와 같은 코드가 나옵니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class C
{
public:
    C() {}
template <typename T>
    C(T const&)
    {
std::cout << “tmpl copy constructor\n”;
    }
};
int main()
{
    C a;
    C b{ a };
}
cs

실행시켜보신 분은 아시겠지만

tmpl copy constructor 이라고 출력이 생각했겠지만 결과는 그와 반대로 아무런 값도 출력이 되지않습니다.

이유는 template 함수는 기본적으로 특별한(예로 복사,이동연산자) 멤버함수로 간주되지 않아 인스턴스화가 되지않고 디폴트 복사 연산자가 호출되게 됩니다.

그럼 어떻게 하면 될까요? 정답은 아래와 같습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class C
{
public:
    C() {}
    C(C const volatile&) = delete;
    template <typename T>
    C(T const&)
    {
        std::cout << “tmpl copy constructor\n”;
    }
};
cs

delete를 이용하여 기존의 복사생성자를 없애버리는건데요.

그치만 논리적으로는 이해가 가지않는코드입니다. 왜 그러면 volatile 키워드는 컴파일러최적화를 하지않고 CPU캐시를 사용하지 못하게 하는 키워드입니다.

일단 제 논리것 설명하자면 디폴트 복사 생성자를 만들지 말아야하는데 delete를 하자니, template로 구현한 복사생성자가 (T const&)를 만들가능성이 있어 volatile을 주어 기존의 복사생성자를 없애버리는 효과가 발생한듯합니다.

 

이 해결방법은 아래의 책에서 나왔습니다. 자세한건 책의 6.4에서 나옵니다.

  • C++ Templates: The Complete Guide (2nd Edition)