개요
C++에는 C에는 없는 namespace라는 문법이 있다.(C가 구식이라서 없는거지 요즘 언어는 어지간하면 다 namespace와 유사한 문법이 있다.) 네임스페이스는 문법이 블럭과 동일하기때문에 내부 영역이 적절히 들여쓰기가 된다
namespace sora {
class SomeClass { };
}
그런데 네임스페이스의 깊이가 항상 1 level일수는 없잖아? 더 깊어질수도 있지 않겠는가? 그렇게 되면 코드가 다음과 같은 꼴이 된다.
namespace sora {
namespace gl {
class SomeClass {
// TODO 적절히 구현하기
};
}
}
고작 네임스페이스 좀 그럴듯하게 보겟다고 코드의 왼쪽공간이 죄다 공백으로 도배되는 참사가 발생한다! 이를 해결하겟다고 irrlicht engine의 경우는 아래처럼 코딩했다.
namespace irr
{
namespace scene
{
class ISceneManager;
typedef core::list<ISceneNode*> ISceneNodeList;
typedef core::list<ISceneNodeAnimator*> ISceneNodeAnimatorList;
//....
일부러 2번쨰 레벨의 네임스페이스를 들여쓰기 없이 사용했다. 하지만 이 방법은 visual studio랑 조합되면 별로 좋은 방법이 아니다. visual studio에서 제공하는 코드 포맷팅을 거치면 어김없이 밀려버린다.
namespace irr
{
namespace scene
{
class ISceneManager;
typedef core::list<ISceneNode*> ISceneNodeList;
typedef core::list<ISceneNodeAnimator*> ISceneNodeAnimatorList;
//....
들여쓰기 없는 다음과 같은 네임스페이스를 쓰기 위해서는 어떻게 짜야 하는가?
namespace sora {
class SomeClass { };
}
;의 순기능
예전에 이를 막기위한 방법을 찾으면서 stackover에서 적절한 편법을 찾았다. namespace를 구성하는 블럭의 {뒤에 ;를 붙여주는 거다
namespace sora {;
class SomeClass { };
}
다만 이 방법에 한가지 문제가 있다면 visual studio에서만 지원한다. xcode같은거로 저 코드를 그래도 들고가서 자동 포맷팅을 한번 돌려주면 들여쓰기가 개발살 나는걸 볼수있다.
매크로
cocos2d-x 에서 사용하는 편법이다.
#define NS_CC_BEGIN namespace cocos2d {
#define NS_CC_END }
NS_CC_BEGIN
class SomeClass { };
NS_CC_END
매크로를 사용하기 때문에 왠지 코드가 이상해보이지만 멀쩡히 작동한다. 매크로를 해석해서 치환하지 않으면 namespace라는걸 알수 없기 떄문에 자동 포맷팅에 의한 강제 들여쓰기도 피할수 없다. cocos2d-x를 처음쓸때는 왜 저짓을 햇나 한참 고민했엇는데 어제밤에 자다가 깨달은 좋은 편법이다
내가 채택한 방법
기본적으로는 cocos2d-x와 같이 매크로를 쓰는 기법을 채택했다. namespace 문법에 유사하게 만들기 위해서 매크로 함수같은 느낌으로 만들었다
#define SR_NS_BEGIN(NS) namespace NS {
#define SR_NS_END(NS) }
SR_NS_BEGIN(sora)
SR_NS_END(sora)
추가 잡소리
namespace에 들여쓰기가 없어짐으로써 코드의 끝부분이 읽기 어려워질수도 있다. 함수와 네임스페이스의 끝이 같이 섞여서 }가 계속 나오기 때문이다.
namespace sora {;
void print() {
//TODO PROFIT!?
}
}
이를 방지하기 위해서 네임스페이스의 끝에 주석을 달아서 끝을 명시적으로 표현하기도 한다. google-coding-style
namespace sora {;
void print() {
//TODO PROFIT!?
}
} // namespace sora