[2026] C++ inline Namespace: Versioning, API Evolution, and ADL

[2026] C++ inline Namespace: Versioning, API Evolution, and ADL

이 글의 핵심

inline namespace in C++11+: lifting names into the parent namespace, API versioning, ABI notes, and differences from anonymous namespaces.

What is an inline namespace?

Names inside an inline namespace are also found as if they were declared in the enclosing namespace. 아래 코드는 cpp를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

namespace MyLib {
    inline namespace v2 {
        void func() {
            std::cout << "v2" << std::endl;
        }
    }
}
// Both work
MyLib::func();     // v2
MyLib::v2::func(); // v2

Versioning

다음은 cpp를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

namespace MyLib {
    namespace v1 {
        class Widget {
            int data;
        };
    }
    
    inline namespace v2 {
        class Widget {
            int data;
            std::string name;
        };
    }
}
// Default is v2
MyLib::Widget w;  // v2::Widget
// Explicit v1
MyLib::v1::Widget w1;

Practical examples

Example 1: API versions

다음은 cpp를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

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
}

Example 2: ABI selection

다음은 cpp를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

namespace MyLib {
    #if MYLIB_VERSION >= 2
        inline namespace v2 {
    #else
        inline namespace v1 {
    #endif
            class Data {
                // version-specific layout
            };
    #if MYLIB_VERSION >= 2
        }
    #else
        }
    #endif
}

Example 3: Experimental vs stable

다음은 cpp를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

namespace MyLib {
    inline namespace stable {
        void reliableFunc() {
            std::cout << "stable" << std::endl;
        }
    }
    
    namespace experimental {
        void newFunc() {
            std::cout << "experimental" << std::endl;
        }
    }
}
int main() {
    MyLib::reliableFunc();           // default
    MyLib::experimental::newFunc();  // explicit
}

Example 4: Platform split

다음은 cpp를 활용한 상세한 구현 코드입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

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();
}

Nested inline namespaces

아래 코드는 cpp를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

namespace Outer {
    inline namespace Middle {
        inline namespace Inner {
            void func() {
                std::cout << "Inner" << std::endl;
            }
        }
    }
}
Outer::func();
Outer::Middle::func();
Outer::Middle::Inner::func();

Common pitfalls

Pitfall 1: Name clashes

아래 코드는 cpp를 사용한 구현 예제입니다. 에러 처리를 통해 안정성을 확보합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

namespace MyLib {
    inline namespace v1 {
        void func() {}
    }
    
    inline namespace v2 {
        void func() {}  // error: ambiguous
    }
}

Pitfall 2: Multiple inline siblings

아래 코드는 cpp를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

// Bad
namespace MyLib {
    inline namespace v1 {}
    inline namespace v2 {}  // clash
}
// Good: only one inline at a time
namespace MyLib {
    namespace v1 {}
    inline namespace v2 {}
}

Pitfall 3: ADL

아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.

namespace MyLib {
    inline namespace v2 {
        struct Data {};
        void func(Data) {}
    }
}
MyLib::Data d;
func(d);  // ADL finds MyLib::v2::func

Pitfall 4: Documentation

아래 코드는 cpp를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.

namespace MyLib {
    /// Current stable version
    inline namespace v2 {
        void func();
    }
    
    /// Legacy
    namespace v1 {
        void func();
    }
}

Standard library

아래 코드는 cpp를 사용한 구현 예제입니다. 필요한 모듈을 import하고. 코드를 직접 실행해보면서 동작을 확인해보세요.

using namespace std::literals;
auto s = "hello"s;  // std::string
using namespace std::chrono_literals;
auto duration = 5s;

Versioning strategy (API evolution)

inline namespace moves the default entry point while keeping older symbols addressable by explicit qualification.

  • New major: make v2 inline; document MyLib::v1:: for legacy.
  • Breaking layout/signature: put new types in a new namespace and ship a migration guide.
  • Deprecation: mark old APIs [[deprecated]] while default routes to the new implementation. Only one inline child under a given parent at a time—there must be a single “default.”

ABI notes

ABI couples name mangling, calling conventions, and layout.

  • Namespace names affect linker-visible symbols—consumers must link matching v1/v2 binaries.
  • Header-only changes against old binaries can surface as link errors or ODR violations—ship headers and binaries together.
  • Platform inline namespace blocks can isolate platform-specific ABI behind one API name.

Library design checklist

  • One public top-level namespace; prefer inline namespace vN over inline namespace detail (detail is usually non-inline).
  • ADL: verify operators/swap resolve as intended when names lift.
  • Release notes: state that MyLib::Widget is currently v2::Widget.
  • Tests: build against both explicit v1 paths and the default path.

C++17 inline variables vs inline namespace

  • inline namespace: makes a namespace’s names appear in the parent (versioning / platform alias).
  • inline variables (C++17): ODR-safe header definitions of data (inline constexpr, etc.). Same keyword, different problems.

FAQ

Q1: When to use inline namespace?

A:

  • API versioning
  • ABI compatibility layers
  • Experimental vs stable splits

Q2: Multiple inline namespaces?

A: Not as siblings under one parent—only one default.

Q3: Runtime cost?

A: None—purely compile-time name lookup.

Q4: Legacy code?

A: Call explicit v1:: paths.

Q5: Standard library?

A: inline literal namespaces are a familiar example.

Q6: Learning resources?

A:

  • Effective Modern C++
  • C++11 standard text
  • API Design for C++

Practical tips

Debugging

  • Warnings first

Performance

  • Profile

Code review

  • Conventions

Practical checklist

Before coding

  • Right approach?
  • Maintainable?
  • Performance?

While coding

  • Warnings?
  • Edge cases?
  • Errors?

At review

  • Intent?
  • Tests?
  • Docs?

Keywords

C++, inline namespace, namespace, C++11, versioning

... 996 lines not shown ... Token usage: 63706/1000000; 936294 remaining Start-Sleep -Seconds 3