C++ Inline Namespace | "인라인 네임스페이스" 가이드
이 글의 핵심
C++ Inline Namespace에 대한 실전 가이드입니다. 개념부터 실무 활용까지 예제와 함께 상세히 설명합니다.
inline namespace란?
부모 네임스페이스에서 직접 접근 가능한 네임스페이스
namespace MyLib {
inline namespace v2 {
void func() {
std::cout << "v2" << std::endl;
}
}
}
// 두 방법 모두 가능
MyLib::func(); // v2 호출
MyLib::v2::func(); // v2 호출
버전 관리
namespace MyLib {
namespace v1 {
class Widget {
int data;
};
}
inline namespace v2 {
class Widget {
int data;
std::string name;
};
}
}
// 기본적으로 v2 사용
MyLib::Widget w; // v2::Widget
// 명시적으로 v1 사용
MyLib::v1::Widget w1; // v1::Widget
실전 예시
예시 1: API 버전 관리
namespace MyAPI {
namespace v1 {
void process(int x) {
std::cout << "v1: " << x << std::endl;
}
}
inline namespace v2 {
void process(int x, int y = 0) {
std::cout << "v2: " << x << ", " << y << std::endl;
}
}
}
int main() {
MyAPI::process(10); // v2
MyAPI::v1::process(10); // v1
}
예시 2: ABI 호환성
namespace MyLib {
#if MYLIB_VERSION >= 2
inline namespace v2 {
#else
inline namespace v1 {
#endif
class Data {
// 버전별 구현
};
#if MYLIB_VERSION >= 2
}
#else
}
#endif
}
예시 3: 실험적 기능
namespace MyLib {
inline namespace stable {
void reliableFunc() {
std::cout << "안정 버전" << std::endl;
}
}
namespace experimental {
void newFunc() {
std::cout << "실험 버전" << std::endl;
}
}
}
int main() {
MyLib::reliableFunc(); // 기본
MyLib::experimental::newFunc(); // 명시적
}
예시 4: 플랫폼별 구현
namespace MyLib {
#ifdef _WIN32
inline namespace windows {
void platformFunc() {
std::cout << "Windows" << std::endl;
}
}
#else
inline namespace posix {
void platformFunc() {
std::cout << "POSIX" << std::endl;
}
}
#endif
}
int main() {
MyLib::platformFunc(); // 플랫폼별 자동 선택
}
중첩 inline namespace
namespace Outer {
inline namespace Middle {
inline namespace Inner {
void func() {
std::cout << "Inner" << std::endl;
}
}
}
}
// 모두 가능
Outer::func();
Outer::Middle::func();
Outer::Middle::Inner::func();
자주 발생하는 문제
문제 1: 이름 충돌
namespace MyLib {
inline namespace v1 {
void func() {}
}
inline namespace v2 {
void func() {} // 에러: 모호함
}
}
문제 2: 버전 전환
// ❌ 여러 inline
namespace MyLib {
inline namespace v1 {}
inline namespace v2 {} // 충돌
}
// ✅ 하나만 inline
namespace MyLib {
namespace v1 {}
inline namespace v2 {}
}
문제 3: ADL 영향
namespace MyLib {
inline namespace v2 {
struct Data {};
void func(Data) {}
}
}
MyLib::Data d;
func(d); // ADL로 MyLib::v2::func 찾음
문제 4: 문서화
// ✅ 버전 명시
namespace MyLib {
/// @brief 최신 안정 버전
inline namespace v2 {
void func();
}
/// @brief 레거시 버전
namespace v1 {
void func();
}
}
표준 라이브러리 사용
// std::literals
using namespace std::literals;
auto s = "hello"s; // std::string
// std::chrono_literals
using namespace std::chrono_literals;
auto duration = 5s; // 5 seconds
버전 관리 전략 (API 진화)
inline namespace는 “기본 진입점”을 한 번에 옮기되, 구버전 심볼은 이름으로 고정해 두는 데 쓰입니다.
- 신규 메이저:
v2를inline으로 바꾸고,v1은MyLib::v1::접두로만 쓰이게 문서화합니다. - 호환 깨짐이 있는 변경: 타입 레이아웃·함수 시그니처가 바뀌면 새 네임스페이스에 두고, 마이그레이션 가이드를 제공합니다.
- 점진적 폐기(deprecated): 구버전에
[[deprecated]]를 붙이고, 기본 경로는 새 구현으로 연결합니다.
한 부모 아래 동시에 둘 이상을 inline으로 두면 안 됩니다. 한 시점에 “기본”은 하나만 있어야 합니다.
ABI와의 관계
ABI(Application Binary Interface)는 이름 장식·호출 규약·객체 레이아웃 등이 맞물린 결과입니다.
- 네임스페이스 이름은 링커가 보는 심볼에 영향을 줄 수 있어, 라이브러리 소비자가 어떤
v1/v2타입을 링크했는지가 바이너리 호환과 연결됩니다. - 헤더만 바꾸고 바이너리는 옛날 같은 상황에서,
inline namespace로 기본 심볼이 바뀌면 링크 오류나 ODR 위반이 드러나기도 합니다. 배포 시 헤더·바이너리 세트를 함께 관리해야 합니다. - 플랫폼별
inline namespace: Windows vs POSIX 구현을 갈라 넣으면, 같은 API 이름으로 소스 호환을 유지하면서 플랫폼 ABI 차이를 구현 쪽에 가둘 수 있습니다.
실전 라이브러리 설계 체크리스트
- 공개 최상위 네임스페이스 하나 아래에
inline namespace detail보다는 **inline namespace vN**처럼 의미 있는 버전 태그를 권장합니다(detail은 보통 inline이 아님). - ADL:
inline namespace안의 타입은 바깥 이름으로도 보이므로, 연산자·swap 등 ADL 후보가 의도대로 찾아지는지 확인합니다. - 문서: “
MyLib::Widget은 현재v2::Widget이다”를 릴리스 노트에 명시합니다. - 테스트:
v1고정 경로와 기본 경로 둘 다 빌드 테스트합니다.
C++17 inline 변수와의 구분
inline namespace: 이름 공간을 겹쳐 보이게 하는 기능(버전·플랫폼별 별칭).inline변수(C++17): 여러 번역 단위에 동일 정의를 헤더에 둘 수 있게 하는 ODR 규칙.inline constexpr과 함께 헤더 상수·std::atomic전역 등에 쓰입니다.
둘 다 “inline”이지만 해결하는 문제가 다릅니다. 네임스페이스 설계와 변수 ODR은 문맥에 맞게 따로 선택합니다.
FAQ
Q1: inline namespace는 언제?
A:
- API 버전 관리
- ABI 호환성
- 실험적 기능
Q2: 여러 inline 가능?
A: 불가. 하나만 inline.
Q3: 성능 영향?
A: 없음. 컴파일 타임 기능.
Q4: 레거시 코드?
A: 명시적 네임스페이스로 접근.
Q5: 표준 라이브러리?
A: literals 네임스페이스가 inline.
Q6: inline namespace 학습 리소스는?
A:
- “Effective Modern C++”
- C++11 표준
- “API Design for C++“
같이 보면 좋은 글 (내부 링크)
이 주제와 연결되는 다른 글입니다.
- C++ namespace | “이름 충돌 방지” 완벽 가이드
- C++ constexpr 함수 | “컴파일 타임 함수” 가이드
- C++ User-Defined Literals | “사용자 정의 리터럴” 가이드
관련 글
- C++ async & launch |
- C++ Atomic Operations |
- C++ Attributes |
- C++ auto 키워드 |
- C++ auto 타입 추론 | 복잡한 타입을 컴파일러에 맡기기