Key가 있어야만 생성가능한 클래스만들기.

다음과 같은 상황을 가정하자.
 특정 객체의 직접 생성을 막고 오직 factory function을 통해서만 객체를 생성할 수 있도록 하게 하려고 한다. 이럴 경우는 생성자를 private로 선언하고 클래스내의 factory function에서 private인 생성자를 호출하면 된다.


즉 위와 같이 작성하면 충분하다.
 그런데 C++11에서 std::vector의 emplace_back, std::make_shared같이 내부적으로 arguments를 forwarding하여 생성자를 호출하는 함수를 사용할 경우에는 생성자가 private이기 때문에 위의 코드는 컴파일에러를 띄운다. 그렇다고 생성자를 단순히 public으로 놔버리면 초기의 목표에 모순이 된다.

 첫번째 해결책으로 friend keyword를 떠올릴수있다. 그러나 이것은 일반적이고 쉬운 해결책은 아닌 것 같다. 일단 나의 경우 std::make_shared 에 friend선언을 하기 위해서 정보를 찾아봤는데 컴파일러버전마다 friend 선언이 달라진다고 한다.


make_shared 외에 다른 것들에 대해서는 확인해보지 않았지만 일단 make_shared 만으로 제너럴하게 적용할 수 없기 때문에 좋은 방법은 아닌 것 같다. 그리고 일일히 friend 선언을 해줘야하므로 성가시고 귀찮다고 할 수 있다.
 그래서 두번째 해결책을 소개하려고 한다. 이 것은 일종의 PrivateKey(HiddenKey) Class를 이용하는 방법이다.



 코드를 그냥 보는 것이 이해가 빠를 것이다. A의 진짜 생성자(A())는 private로 감춰져있다. 하지만 A()로 리다이렉트되는 A(PrivateKey) 생성자가 public으로 공개되어있다. 하지만 PrivateKey가 있어야만 입장가능(?)하다. 하지만 PrivateKey는 private임으로 자기맘대로 가질수는 없다. 따라서 외부에서는 PrivateKey를 얻을 수 없기때문에 A객체를 생성할 수 없고, A class 내부에서 make_shared를 호출할때, PrivateKey를 넘겨줌으로써 A객체를 생성할 수 있게 된다.

역시 C++은 재밌어!

http://stackoverflow.com/questions/11425576/private-constructor-inhibits-use-of-emplace-back-to-avoid-a-move
http://stackoverflow.com/questions/7521660/friend-function-of-stdmake-shared-in-visual-studio-2010-not-boost

댓글