C++ Redefine

Languages: [EN] English | [KO] 한국어

C++ Redefine: A New C++ Programming Model
C++ Redefine: 새로운 C++ 프로그래밍 모델

<Even in death I still serve>

C++ Redefine: c++ -20 v0.0.1

  1. Introduction
    • This document proposes a programming model that structurally resolves C++'s chronic problems (memory bugs, unclear ownership, abstraction costs, spaghetti code) without replacing the language itself. By integrating context-based ownership, namespace-based access control, and function pointer-based execution models, it addresses the same problems Rust attempts to solve at the language level, but at the structural level instead.
    • Since most of the unique features of C++ have been structurally excluded, some modifications (such as namespaces) can be applied equally to the C environment
    • This document is not a conceptual proposal, but a verified implementation spec from an actively running project - Smeltrix
  2. Before / After
    • Before this model was established, modifying a single function often required tracking 5~6 related files due to hidden dependencies between classes. The actual fix took minutes, but finding where to fix took a long time.
    • After applying C++ Redefine, the file boundary is the access boundary. Modifications are structurally contained within the owning module. There is no need to trace hidden dependencies.
    • This is not merely a claim - it is the direct experience that forced a complete redesign of the project that later became Smeltrix.
  3. Naming Convention (How, What, Kind)
    • How: define, set, get, live, cache, max, min, active, is, buf
    • What: A descriptive noun identifying the purpose. EX: CPU, GPU, TDP
    • Kind: Unit or type such as W, MHz, IDX, C
    • Examples: define_max_power_W, get_live_temp_C, set_active_IDX
    • This convention ensures consistent readability and intent across the entire codebase. The role of any variable is immediately apparent from its name alone, without additional comments.
  4. Context Model
    • All state must be declared exclusively within the context of its corresponding cpp file.
    • Initialization within the context is recommended using C++20 or later. If not possible, direct initialization in main.cpp is permitted. In either case, uninitialized state is not allowed.
    • Variable definitions inside code blocks are prohibited(State -> Context, Temporaries -> Stack). Declarations are only permitted within the context.
    • Context lifetime is guaranteed until program termination. If cleanup is required, the owning module handles it. Thread lifetime follows context lifetime.
    • Multithreading and code reuse have been validated through Smeltrix, but are not covered here due to the extensive content involved. This topic will be addressed in a separate post.
    • Hot data context must include the following three static assertions:
      • static_assert(sizeof(Context) <= 64, "Heresy detected: Size overflow"); - size must be a multiple of 64, change the value 64 to match your requirement
      • static_assert(std::is_trivially_copyable_v<Context>); - proves no heap usage
      • static_assert(std::is_standard_layout_v<Context>); - predictable memory layout
  5. Namespace Ownership Model
    • All code must be separated by namespace. A single file may only use one namespace.
    • Ownership of a context belongs exclusively to main.cpp of the same namespace. Sub-namespaces can naturally access the parent context without argument passing.
    • public/private access control from class is replaced by static func() within the namespace of each file. The file boundary is the access boundary.
    • When referencing the full namespace path, specify an absolute path (::Ex). Using relative paths is prohibited as it can cause ambiguity.
    • If information from another module is needed, implement borrowing via dereferenced pointer. Ownership remains in the original module, and pointer validity is guaranteed by context lifetime.
    • File split criterion: Responsibility, not LOC. When a namespace exceeds a single role, split into a sub-namespace, File size is a result, not a constraint.
  6. Execution Model
    • The implementation and execution parts are separated through function pointers. The implementation part is separated into the ::Impl namespace, and the execution part is called through FPTable.
    • The FPTable is fixed after initialization and cached in the CPU Branch Target Buffer, resulting in no practical abstraction cost.
    • No-argument design is the default. Argument passing is permitted only for external libraries that cannot be modified.
    • Lambdas are allowed but argument passing is not permitted.
    • Each module owns its own code by default, even for common logic. If project-wide common code is necessary, place it in define.h at the project root, though this is not recommended.
    • Allowed scopes in global define.h: debug flags, version constants, platform branches, common type aliases. State definitions are not allowed.
    • Function pointer indirect calls structurally block static reverse engineering tools from tracing the call graph, providing security benefits without the need for separate obfuscation.
    • Function pointer calls can be converted to direct calls via flags during debug builds, making static analysis and debugger tracing easier.
  7. Error Handling
    • Do not use exceptions in your own code. Error states are also held by the context.
    • try/catch is permitted only for external libraries that may throw (e.g. JSON parsing, file I/O).
  8. Directory Structure
    • Do not separate h/cpp. Organize by module instead.
    • Always use project-relative paths with <> for includes (EX: <core/ex/main.h>). Use of "" is prohibited.
    • Directory names must be synchronized with namespace names. The folder structure is the architecture document.
    • Each module directory contains:
      • context.h - namespace Ex::Context (state ownership)
      • define.h - namespace Ex, static constexpr, type and constant definitions
      • fptable.h - namespace Ex::FPTable (execution model)
      • main.h - namespace Ex (interface)
      • main.cpp - namespace Ex (ownership)
      • impl.h - namespace Ex::Impl (implementation declarations)
      • impl.cpp - namespace Ex (implementation)
  9. Allow / Deny
    • Deny:
      • macro - preprocessor pollution
      • template - code duplication via generation (Do not create custom template<>)
      • class - heap and virtual function overhead
      • auto - type ambiguity (allowed only when the expression is excessively long)
      • enum - global scope pollution
      • inline - No abuse, only allowed under certain conditions, such as when performance is required
      • variable definition in code - state outside context is prohibited
    • Allow:
      • Lambdas (argument passing is not permitted)
      • static constexpr inside context
      • Language features such as class/try/catch for external library support are allowed
  10. Team Structure
    • Junior - handles implementation only. No knowledge of function pointer structure required. The structure itself prevents mistakes.
      • impl.cpp, impl.h - read/write (rw)
      • all other files - read only (r)
    • Senior - manages module connections and execution model. Responsible for FPTable composition and ownership wiring.
      • main.cpp, main.h, fptable.h - read/write (rw)
      • impl.cpp, impl.h - read only (r)
      • all other files - read only (r)
    • Maintainer - designs overall namespace structure and enforces rules. Responsible for context design and module boundary decisions.
      • all files - read/write (rw)
    • Operations Tips
      • impl_name.cpp clearly identifies the responsible developer. Ownership transfer makes accountability explicit.
      • New implementations can be tested by simply swapping FPTable*. Rollback on failure is a one-liner - no git required.
      • Junior developers can create a personal implementation file such as impl_Smith.cpp and verify it via FPTable swap before merging into the mainstream.
  11. The following is a lengthy topic and will be covered in a separate post:
    • Multithreading
    • Code Reuse
    • External API Integration
    • Configuring Pipelines Between Modules
  12. Conclusion
    • C++ Redefine is the result of seeking systematic control during personal project development. It resolves C++'s chronic problems through structural rules alone, without replacing the language. What Rust enforces via the compiler - ownership and safety - this model achieves through file structure and namespace rules.
    • This model is horizontally scalable, with complexity growing linearly as modules increase. This has been validated through standalone maintenance of 40,000 LOC.
    • This architecture provides a clear starting point for beginners learning C++, while also offering experienced C++ developers a way to maintain safety and leverage their existing legacy assets.
  1. 서론
    • 본 문서는 C++의 고질적 문제(메모리 버그, 소유권 불명확, 추상화 비용, 스파게티 코드)를 언어 교체 없이 구조적으로 해소하는 프로그래밍 모델을 제안한다. 컨텍스트 기반 소유권, 네임스페이스 기반 접근 제어, 함수 포인터 기반 실행 모델을 통합함으로써 Rust가 언어 차원에서 해결하려 한 문제들을 구조 차원에서 해소한다.
    • C++ 고유 기능 대부분을 구조적으로 배제하였으므로 일부 수정시(네임스페이스 등) C 환경에서도 동일하게 적용 가능하다.
    • 본 문서는 개념 제안이 아니라 실제 운영 중인 프로젝트 - Smeltrix 에서 검증된 구현 스펙이다.
  2. 적용 전 / 후
    • 본 모델 정립 이전에는 하나의 함수를 수정하면 클래스 간 숨겨진 의존성으로 인해 5~6개의 연관 파일을 추적해야 했다. 실제 수정은 몇 분이지만 어디를 수정해야 하는지 찾는 데 긴 시간이 소요되었다.
    • C++ Redefine 적용 후에는 파일 경계가 곧 접근 경계이므로 수정 범위가 소유 모듈 내에서 구조적으로 완결된다. 숨겨진 의존성을 추적할 필요가 없다.
    • 이는 단순 주장이 아니라 Smeltrix 의 전면 재설계를 했던 직접적인 경험이다.
  3. 네이밍 규칙 (How, What, Kind)
    • How: define, set, get, live, cache, max, min, active, is, buf
    • What: 목적을 명시하는 서술어 EX: CPU, GPU, TDP
    • Kind: W, MHz, IDX, C 등 단위 또는 타입
    • 예시: define_max_power_W, get_live_temp_C, set_active_IDX
    • 이 규칙은 코드 전체에서 일관된 가독성과 의도 파악을 보장하며, 별도의 주석 없이도 변수의 역할이 이름에서 즉시 파악된다.
  4. 컨텍스트 모델 (Context Model)
    • 모든 상태(state)는 반드시 해당 cpp의 컨텍스트 내에서만 선언되어야 한다.
    • c++20 이상을 사용하여 컨텍스트 내 초기화 를 추천하며, 불가능시 main.cpp 에서 직접 초기화 한다, 어느 경우든 미초기화 상태는 허용되지 않는다
    • 코드 내부에서의 변수 정의는 금지(State -> Context, Temporaries -> Stack)되며, 선언은 오직 컨텍스트 안에서만 허용된다.
    • 컨텍스트 수명은 프로그램 종료 시까지 보장된다. 정리가 필요한 경우 해당 모듈이 스스로 처리한다. 스레드 수명 역시 컨텍스트 수명을 따른다.
    • 멀티스레딩과 코드 재사용은 Smeltrix를 통해 검증되었으나, 내용이 길어 여기서 다루지 않는다. 이 주제는 차후 별도의 글에서 다룬다.
    • 핫 데이터 컨텍스트는 다음 세 가지 반드시 포함해야 한다:
      • static_assert(sizeof(Context) <= 64, "Heresy detected: Size overflow"); - size 는 64의 배수여야 하며 코드의 64는 필요한 수치로 변경 하여 사용 한다.
      • static_assert(std::is_trivially_copyable_v<Context>); - 힙 없음 증명
      • static_assert(std::is_standard_layout_v<Context>); - 메모리 레이아웃 예측 가능
  5. 네임스페이스 소유권 모델 (Namespace Ownership)
    • 모든 코드는 네임스페이스 단위로 분리되며, 하나의 파일은 하나의 네임스페이스만 사용한다.
    • 컨텍스트의 소유권은 동일 네임스페이스의 main.cpp에만 귀속된다. 하위 네임스페이스는 상위 컨텍스트에 자연스럽게 접근 가능하다.
    • class의 public/private 접근 제어는 파일 내 네임스페이스의 static func()으로 대체된다. 파일 경계가 곧 접근 경계이다.
    • 네임스페이스 전체 경로 참조 시 절대경로(::Ex)를 명시한다. 상대경로 사용은 모호성을 유발할 수 있으므로 금지한다.
    • 다른 모듈의 정보가 필요한 경우, 포인터 역참조(dereferenced pointer) 형태로 빌림(borrow)을 구현한다. 소유권은 원래 모듈에 유지되며, 포인터의 유효성은 컨텍스트 수명이 보장한다.
    • 파일 분할 기준: LOC 가 아니라 책임이 기준. 네임스페이스가 하나의 역할을 넘으면 서브네임스페이스로 분리. 파일 크기는 결과물이지 제약이 아니기 때문이다.
  6. 실행 모델 (Execution Model)
    • 구현부와 실행부는 함수 포인터를 통해 분리한다. 구현부는 Ex::Impl 네임스페이스로 분리하며, 실행부는 FPTable을 통해 호출된다.
    • FPTable은 초기화 후 고정되며, CPU Branch Target Buffer에 캐싱되므로 실질적 추상화 비용이 없다.
    • 기본적으로 무인자(no-argument)를 지향한다. 외부 라이브러리에 한하여 인자 전달을 허용한다.
    • 람다는 사용 가능하나 인자 전달은 불가하다.
    • 각 모듈은 공통 코드라도 기본적으로 자체 소유를 원칙으로 한다. 프로젝트 전역 공통 코드가 필요한 경우 프로젝트 루트의 define.h를 사용하나, 권장하지 않는다.
    • 전역 define.h의 허용 범위: 디버그 플래그, 버전 상수, 플랫폼 분기, 공통 타입 별칭. state 정의는 허용하지 않는다.
    • 함수 포인터 간접 호출은 정적 역분석 도구의 call graph 추적을 구조적으로 차단하여, 별도 난독화 없이 보안 이점을 제공한다
    • 디버그 빌드 시 플래그를 통해 함수 포인터 호출을 직접 호출로 전환할 수 있어, 정적 분석 및 디버거 추적이 용이하다.
  7. 오류 처리 (Error Handling)
    • 자체 코드에서는 예외(exception)를 사용하지 않는다. 오류 상태 또한 컨텍스트가 보유한다.
    • 예외를 발생시킬 수 있는 외부 라이브러리(예: JSON 파싱, 파일 I/O)에 한하여 try/catch를 허용한다.
  8. 디렉토리 구조 (Directory Structure)
    • h/cpp 를 분리하지 않고 모듈 단위로 구성한다.
    • include 경로는 항상 프로젝트 경로 포함 기준 (EX: <core/ex/main.h>) <>를 사용하며 ""는 금지한다.
    • 디렉토리명은 반드시 네임스페이스명과 동기화한다. 폴더 구조가 곧 아키텍처 문서이다.
    • 각 모듈 디렉토리의 구성:
      • context.h - namespace Ex::Context (상태 소유)
      • define.h - namespace EX -> static constexpr, 필요한 타입 및 상수 정의
      • fptable.h - namespace Ex::FPTable (실행 모델)
      • main.h - namespace Ex (인터페이스)
      • main.cpp - namespace Ex (소유권 귀속)
      • impl.h - namespace Ex::Impl (구현 선언)
      • impl.cpp - namespace Ex (구현부)
  9. 허용 및 금지 목록 (Allow / Deny)
    • 금지(Deny):
      • macro - 전처리기 오염
      • template - 코드 복사 생성 (사용자 정의 template<>)
      • class - 힙/가상함수
      • auto - 타입 모호성 (단, 표현이 지나치게 길어질 경우 예외적으로 허용)
      • enum - 전역 오염
      • inline - 남용 금지, 성능이 요구되는 등, 특정 조건에서만 허용
      • 코드 내 변수 정의 - 컨텍스트 외부의 상태 금지
    • 허용(Allow):
      • 람다 (단, 인자 전달 불가)
      • 컨텍스트 내 static constexpr
      • 외부 라이브러리 대응을 위한 class/try/catch 등 언어 기능은 허용
  10. 팀 구조 및 파일 접근 권한 (Team Structure)
    • Junior - 구현부만 담당. 함수 포인터 구조를 몰라도 되며, 구조가 실수를 차단한다.
      • impl.cpp, impl.h - 읽기/쓰기 (rw)
      • 나머지 파일 - 읽기 전용 (r)
    • Senior - 모듈 연결 및 실행 모델 관리. FPTable 구성과 소유권 연결을 담당한다.
      • main.cpp, main.h, fptable.h - 읽기/쓰기 (rw)
      • impl.cpp, impl.h - 읽기 전용 (r)
      • 나머지 파일 — 읽기 전용 (r)
    • Maintainer - 전체 네임스페이스 구조 설계 및 룰 유지. context 설계와 모듈 경계 결정을 담당한다.
      • 전체 파일 - 읽기/쓰기 (rw)
    • 운영 팁
      • impl_name.cpp 로 구현 책임자 표시 및 소유권 이양으로 책임 소재 명확화
      • FPTable* 교체만으로 새로운 구현 테스트 가능, 오류 시 롤백이 한 줄로 완료 - git 없이도 원복 가능
      • Junior 테스트 시 impl_kim.cpp 처럼 개인 구현부를 별도 파일로 작성 후 FPTable 교체로 메인스트림 투입 전 검증 가능
  11. 다음 내용은 내용이 길어 차후 별도의 글에서 다룬다:
    • 멀티스레딩
    • 코드 재사용
    • 외부 API 연동
    • 모듈 간 파이프라인 구성
  12. 결론
    • C++ Redefine은 본인의 프로젝트를 진행하며 체계적 관리를 위해 도출된 결과물이며, 언어를 교체하지 않고, 구조적 규칙만으로 C++의 고질적 문제를 해소한다. Rust가 컴파일러로 강제하는 소유권과 안전성을, 본 모델은 파일 구조와 네임스페이스 규칙으로 구현한다.
    • 이 모델은 수평적 확장이 가능하며, 모듈이 늘어나도 복잡도가 선형으로 증가한다. 40,000 LOC 의 단독 유지로 이를 검증하였다.
    • C++을 처음 배우는 입문자에게도 이 구조는 명확한 시작점을 제공하며, 기존 C++ 전문가의 레거시 자산을 그대로 활용하면서 안전성을 확보하는 경로를 제시한다.

© http://project-ap.blogspot.com. This work is licensed under CC BY-ND 4.0. You may share this work freely, but you must give appropriate credit and may not distribute modified versions.

🔵 The Structured Brotherhood Structure is strength. Chaos is build failure. "My domain. My rules. My cpp."
🔴 The Corrupted Warband We promised safety. We brought borrow checker. "We never promised comfort."
🟢 The Simple Horde LGTM. Ship it. "Duplication over abstraction. Always."
🟡 The Machine Cult Write Once. Run Anywhere. Slowly. "The JVM is eternal. The cache line is not."
🐛 The Endless Swarm pip install everything. "dependency_hell==True"

C++ Redefine template code v0.0.1 (based on c++20)

  • context.h

    //================================================================================ // // this code written by http://project-ap.blogspot.com/ // // Copyright (C) 2026 http://project-ap.blogspot.com/ // // This code is released under the MIT License. // Permission is hereby granted, free of charge, to any person obtaining // a copy of this code to use, copy, modify, merge, publish, distribute, // sublicense, and/or sell copies, subject to the above copyright notice // being included in all copies. // // For more information, please visit the blog address above. //================================================================================ #pragma once namespace Ex { struct Context { // Whatever you need int* id = nullptr; int clientid = -1; }; extern Context ctx; } //********************************************** // Uncomment after defining your struct with Hot data // Cold Data doesn't need these. //********************************************** // Waiting for excommunication //static_assert(sizeof(::Ex::Context::YourStruct) <= 64, "Heresy detected: Size overflow"); // required alignas(64) with YourStruct //static_assert(std::is_trivially_copyable_v<::Ex::Context::YourStruct>); //static_assert(std::is_standard_layout_v<::Ex::Context::YourStruct>);
  • define.h

    #pragma once namespace Ex { struct Info { static constexpr int USR = 1; }; }
  • fptable.h

    #pragma once namespace Ex { typedef void (*FnVoidNoArgs)(); struct FPTable { FnVoidNoArgs Init; }; extern FPTable* Current; extern FPTable FPTDefault; }
  • main.h

    #pragma once namespace Ex { void Init(); }
  • main.cpp

    <example/context.h> <example/define.h> <example/fptable.h> <example/impl.h> <example/main.h> namespace Ex { Context ctx; FPTable FPTDefault = { Impl::DoSomething }; #if defined(YourCondition) FPTable* Current = &FPTDefault; #else //FPTable* Current = Put Your Table; #endif void Init() { // Do Someting Current->Init(); } }
  • impl.h

    #pragma once namespace Ex::Impl { void DoSomething(); }
  • impl.cpp

    <example/context.h> <cstdio> namespace Ex::Impl { void DoSomething() { printf("%d", ctx.clientid); } }

Template code is released under the MIT License. Copyright © http://project-ap.blogspot.com. Permission is hereby granted, free of charge, to any person obtaining a copy of this code to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies, subject to the above copyright notice being included in all copies.

Comments