From 8a813f1733d0f4030b2baa751b6b98a8a9efce4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Wed, 21 Jan 2026 02:51:19 +0100 Subject: [PATCH 1/7] Fix build for modern C++17 and Clang 17 Modernize the project to build with contemporary toolchains: - Upgrade C++ standard from C++11 to C++17 - Update CMake minimum version to 3.16 - Fix logger comparator const-correctness for modern libc++ - Resolve namespace/class name ambiguity using inline variables - Use typedef alias to disambiguate out-of-line member definitions The dotenv class name matches its namespace, which causes parsing issues in modern C++. Fixed by using C++17 inline variables for static members and a typedef alias in the implementation. --- CMakeLists.txt | 4 ++-- common/libs/antlr4-cpp-runtime/CMakeLists.txt | 4 ++-- include/dotenv.h | 8 ++++++-- src/common/logger.cpp | 2 +- src/common/logger.h | 2 +- src/dotenv.cpp | 18 ++++++++++-------- 6 files changed, 22 insertions(+), 16 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2c7a502..9fb67a4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,8 @@ #----------------------- PROJECT CONFIGURATION -------------------------------- -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(cpp-dotenv VERSION 1.0.0) -set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) if ("${CMAKE_BUILD_TYPE}" STREQUAL "") diff --git a/common/libs/antlr4-cpp-runtime/CMakeLists.txt b/common/libs/antlr4-cpp-runtime/CMakeLists.txt index 1b488f2..c208123 100644 --- a/common/libs/antlr4-cpp-runtime/CMakeLists.txt +++ b/common/libs/antlr4-cpp-runtime/CMakeLists.txt @@ -1,7 +1,7 @@ -cmake_minimum_required(VERSION 3.0.2) +cmake_minimum_required(VERSION 3.10) project(antlr4-cpp-runtime VERSION 4.8) -set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) if ("${CMAKE_BUILD_TYPE}" STREQUAL "") diff --git a/include/dotenv.h b/include/dotenv.h index 1b3a9c8..851376a 100644 --- a/include/dotenv.h +++ b/include/dotenv.h @@ -15,7 +15,7 @@ namespace dotenv public: - dotenv& load_dotenv(const std::string& dotenv_path = env_filename, + dotenv& load_dotenv(const std::string& dotenv_path = ".env", const bool overwrite = false, const bool interpolate = true); @@ -28,7 +28,7 @@ namespace dotenv void operator=(const dotenv&) = delete; static dotenv& instance(); - + private: dotenv() = default; @@ -42,4 +42,8 @@ namespace dotenv extern dotenv& env; + + // Inline variables defined after class is complete (C++17) + inline const std::string dotenv::env_filename = ".env"; + inline dotenv dotenv::_instance; } diff --git a/src/common/logger.cpp b/src/common/logger.cpp index 9430cf1..b335605 100644 --- a/src/common/logger.cpp +++ b/src/common/logger.cpp @@ -21,7 +21,7 @@ bool logger::position::operator<(const position& p) const } -bool logger::position::less::operator()(const position& p1, const position& p2) +bool logger::position::less::operator()(const position& p1, const position& p2) const { return p1 < p2; } diff --git a/src/common/logger.h b/src/common/logger.h index f2a91a3..4daa68e 100644 --- a/src/common/logger.h +++ b/src/common/logger.h @@ -31,7 +31,7 @@ namespace dotenv struct less { - bool operator()(const position& p1, const position& p2); + bool operator()(const position& p1, const position& p2) const; }; public: diff --git a/src/dotenv.cpp b/src/dotenv.cpp index 89bd3c1..89585f9 100644 --- a/src/dotenv.cpp +++ b/src/dotenv.cpp @@ -8,10 +8,14 @@ using namespace std; -using namespace dotenv; -dotenv::dotenv& dotenv::dotenv::load_dotenv(const string& dotenv_path, const bool overwrite, const bool interpolate) +// Typedef to work around the fact that class name matches namespace name +// This is a known C++ limitation when defining out-of-line members +typedef class ::dotenv::dotenv Dotenv_Type; + + +Dotenv_Type& ::dotenv::dotenv::load_dotenv(const string& dotenv_path, const bool overwrite, const bool interpolate) { ifstream env_file; env_file.open(dotenv_path); @@ -27,19 +31,17 @@ dotenv::dotenv& dotenv::dotenv::load_dotenv(const string& dotenv_path, const boo } -const dotenv::dotenv::value_type dotenv::dotenv::operator[](const key_type& k) const +auto ::dotenv::dotenv::operator[](const key_type& k) const -> const string { return getenv(k).second; } -dotenv::dotenv& dotenv::dotenv::instance() +Dotenv_Type& ::dotenv::dotenv::instance() { return _instance; } -const string dotenv::dotenv::env_filename = ".env"; -dotenv::dotenv dotenv::dotenv::_instance; - -dotenv::dotenv& dotenv::env = dotenv::instance(); +// Static members are now inline in the header (C++17) +::dotenv::dotenv& ::dotenv::env = ::dotenv::dotenv::instance(); From 9d3f65ba8b20afe0a490a860f8263c84e1c46e07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Wed, 21 Jan 2026 03:11:47 +0100 Subject: [PATCH 2/7] Add BUILD_BOTH_LIBRARIES option to build static and shared libs Add a new CMake option BUILD_BOTH_LIBRARIES that allows building both static and shared libraries in a single build directory. This provides an alternative to the existing approach of building in separate directories with BUILD_SHARED_LIBS=ON/OFF, while maintaining backward compatibility with existing build scripts. Usage: cmake .. -DBUILD_BOTH_LIBRARIES=ON Produces: - libcpp_dotenv_static.a - libcpp_dotenv_shared.so (or .dylib on macOS) --- CMakeLists.txt | 58 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9fb67a4..092378c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,9 @@ else() endif() message(STATUS "Building CPP-DOTENV in ${CMAKE_BUILD_TYPE} mode") +# Option to build both static and shared libraries +option(BUILD_BOTH_LIBRARIES "Build both static and shared libraries" OFF) + #------------------- SUBDIRECTORY ADDITION ------------------------------------ add_subdirectory(common) @@ -19,29 +22,58 @@ add_subdirectory(src) #----------------------- LIBRARY CONFIGURATION -------------------------------- -set(CPP_DOTENV cpp_dotenv CACHE INTERNAL "") set(CPP_DOTENV_SRC src/dotenv.cpp include/dotenv.h ) -add_library(${CPP_DOTENV} ${CPP_DOTENV_SRC}) +# Common include directories +set(CPP_DOTENV_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include) -target_link_libraries(${CPP_DOTENV} - ${ENVIRON_LIB} - ${PARSER_LIB} -) +# Common compile options +if ("${CMAKE_BUILD_TYPE}" STREQUAL "DEBUG") + set(CPP_DOTENV_COMPILE_OPTIONS -g -Wall -O0) +else() + set(CPP_DOTENV_COMPILE_OPTIONS -O3) +endif() -target_include_directories(${CPP_DOTENV} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/include -) +# Build both static and shared libraries if requested +if(BUILD_BOTH_LIBRARIES) + # Static library + add_library(cpp_dotenv_static STATIC ${CPP_DOTENV_SRC}) + target_link_libraries(cpp_dotenv_static + ${ENVIRON_LIB} + ${PARSER_LIB} + ) + target_include_directories(cpp_dotenv_static PUBLIC ${CPP_DOTENV_INCLUDE_DIRS}) + target_compile_options(cpp_dotenv_static PRIVATE ${CPP_DOTENV_COMPILE_OPTIONS}) -if ("${CMAKE_BUILD_TYPE}" STREQUAL "DEBUG") - target_compile_options(${CPP_DOTENV} PRIVATE - -g -Wall -O0 + # Shared library + add_library(cpp_dotenv_shared SHARED ${CPP_DOTENV_SRC}) + target_link_libraries(cpp_dotenv_shared + ${ENVIRON_LIB} + ${PARSER_LIB} ) + target_include_directories(cpp_dotenv_shared PUBLIC ${CPP_DOTENV_INCLUDE_DIRS}) + target_compile_options(cpp_dotenv_shared PRIVATE ${CPP_DOTENV_COMPILE_OPTIONS}) + + # Alias for compatibility - default to static + add_library(cpp_dotenv ALIAS cpp_dotenv_static) else() + # Single library (type determined by BUILD_SHARED_LIBS) + set(CPP_DOTENV cpp_dotenv CACHE INTERNAL "") + add_library(${CPP_DOTENV} ${CPP_DOTENV_SRC}) + + target_link_libraries(${CPP_DOTENV} + ${ENVIRON_LIB} + ${PARSER_LIB} + ) + + target_include_directories(${CPP_DOTENV} PUBLIC + ${CPP_DOTENV_INCLUDE_DIRS} + ) + target_compile_options(${CPP_DOTENV} PRIVATE - -O3 + ${CPP_DOTENV_COMPILE_OPTIONS} ) endif() From 5222c9951344a6db3693af5cd70148343651cca7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Wed, 21 Jan 2026 09:16:56 +0100 Subject: [PATCH 3/7] Address Copilot review feedback for BUILD_BOTH_LIBRARIES - Add validation to prevent BUILD_BOTH_LIBRARIES and BUILD_SHARED_LIBS from being used together (with warning message) - Improve documentation for the cpp_dotenv alias, explaining that it points to cpp_dotenv_static when BUILD_BOTH_LIBRARIES is ON --- CMakeLists.txt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 092378c..802ad6b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,6 +15,12 @@ message(STATUS "Building CPP-DOTENV in ${CMAKE_BUILD_TYPE} mode") # Option to build both static and shared libraries option(BUILD_BOTH_LIBRARIES "Build both static and shared libraries" OFF) +# Validate that BUILD_BOTH_LIBRARIES and BUILD_SHARED_LIBS are not used together +if(BUILD_BOTH_LIBRARIES AND BUILD_SHARED_LIBS) + message(WARNING "BUILD_BOTH_LIBRARIES and BUILD_SHARED_LIBS should not be used together. BUILD_SHARED_LIBS will be ignored.") + set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build shared libraries" FORCE) +endif() + #------------------- SUBDIRECTORY ADDITION ------------------------------------ add_subdirectory(common) @@ -57,7 +63,10 @@ if(BUILD_BOTH_LIBRARIES) target_include_directories(cpp_dotenv_shared PUBLIC ${CPP_DOTENV_INCLUDE_DIRS}) target_compile_options(cpp_dotenv_shared PRIVATE ${CPP_DOTENV_COMPILE_OPTIONS}) - # Alias for compatibility - default to static + # Alias for backward compatibility: + # When BUILD_BOTH_LIBRARIES is ON, the cpp_dotenv target is an alias to + # cpp_dotenv_static. Projects that need the shared library must explicitly + # link against cpp_dotenv_shared instead of cpp_dotenv. add_library(cpp_dotenv ALIAS cpp_dotenv_static) else() # Single library (type determined by BUILD_SHARED_LIBS) From 7bed243a738f3704585c4b862a5af7ea2f23c34c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Wed, 21 Jan 2026 09:52:00 +0100 Subject: [PATCH 4/7] Address remaining Copilot review feedback - Add OUTPUT_NAME property so libraries are named correctly: * libcpp_dotenv.a (static) instead of libcpp_dotenv_static.a * libcpp_dotenv.so/.dylib (shared) instead of libcpp_dotenv_shared.so - Enable CMAKE_POSITION_INDEPENDENT_CODE when building shared libraries to ensure static dependencies are compiled with -fPIC - Document BUILD_BOTH_LIBRARIES option in README.md with usage examples The OUTPUT_NAME property sets only the base name; CMake automatically adds the correct platform-specific extension (.so on Linux, .dylib on macOS). --- CMakeLists.txt | 10 ++++++++++ README.md | 38 +++++++++++++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 802ad6b..2624a29 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,12 @@ if(BUILD_BOTH_LIBRARIES AND BUILD_SHARED_LIBS) set(BUILD_SHARED_LIBS OFF CACHE BOOL "Build shared libraries" FORCE) endif() +# When building shared libraries that link against static libraries, +# we need position-independent code for the static libraries +if(BUILD_SHARED_LIBS OR BUILD_BOTH_LIBRARIES) + set(CMAKE_POSITION_INDEPENDENT_CODE ON) +endif() + #------------------- SUBDIRECTORY ADDITION ------------------------------------ add_subdirectory(common) @@ -53,6 +59,8 @@ if(BUILD_BOTH_LIBRARIES) ) target_include_directories(cpp_dotenv_static PUBLIC ${CPP_DOTENV_INCLUDE_DIRS}) target_compile_options(cpp_dotenv_static PRIVATE ${CPP_DOTENV_COMPILE_OPTIONS}) + # Set output name to libcpp_dotenv.a (instead of libcpp_dotenv_static.a) + set_target_properties(cpp_dotenv_static PROPERTIES OUTPUT_NAME cpp_dotenv) # Shared library add_library(cpp_dotenv_shared SHARED ${CPP_DOTENV_SRC}) @@ -62,6 +70,8 @@ if(BUILD_BOTH_LIBRARIES) ) target_include_directories(cpp_dotenv_shared PUBLIC ${CPP_DOTENV_INCLUDE_DIRS}) target_compile_options(cpp_dotenv_shared PRIVATE ${CPP_DOTENV_COMPILE_OPTIONS}) + # Set output name to libcpp_dotenv.so/.dylib (instead of libcpp_dotenv_shared.so) + set_target_properties(cpp_dotenv_shared PROPERTIES OUTPUT_NAME cpp_dotenv) # Alias for backward compatibility: # When BUILD_BOTH_LIBRARIES is ON, the cpp_dotenv target is an alias to diff --git a/README.md b/README.md index aad33c5..198f6f1 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ Supported build methods are: ### CMake -**cpp-dotenv** comes with support for `CMake` right out of the box. In order to use it, simply include this repository's directory and link the `cpp_dotenv` target to your own targets where needed: +**cpp-dotenv** comes with support for `CMake` right out of the box (>=3.16). In order to use it, simply include this repository's directory and link the `cpp_dotenv` target to your own targets where needed: ```cmake add_subdirectory(cpp-dotenv) @@ -55,6 +55,42 @@ target_link_libraries(YOUR_TARGET cpp_dotenv) After this, you might use the library as described in [usage](#usage); no extra scoping, no need to worry about the project's directory structure. +#### Build Options + +By default, only one library target named `cpp_dotenv` is built. The type of library (static or shared) is controlled by CMake's standard `BUILD_SHARED_LIBS` option: + +```bash +# Build static library (default) +cmake -DBUILD_SHARED_LIBS=OFF .. + +# Build shared library +cmake -DBUILD_SHARED_LIBS=ON .. +``` + +#### Building Both Static and Shared Libraries + +To build both static and shared libraries in a single build directory, use the `BUILD_BOTH_LIBRARIES` option: + +```bash +cmake -DBUILD_BOTH_LIBRARIES=ON .. +``` + +This creates two separate library targets: +- `cpp_dotenv_static` - outputs as `libcpp_dotenv.a` +- `cpp_dotenv_shared` - outputs as `libcpp_dotenv.so` (or `.dylib` on macOS) + +For backward compatibility, the `cpp_dotenv` target remains available as an alias to `cpp_dotenv_static`. If you need to link against the shared library, explicitly specify `cpp_dotenv_shared`: + +```cmake +# Link against static library (default) +target_link_libraries(YOUR_TARGET cpp_dotenv) + +# Link against shared library +target_link_libraries(YOUR_TARGET cpp_dotenv_shared) +``` + +**Note:** When `BUILD_BOTH_LIBRARIES` is enabled, `BUILD_SHARED_LIBS` is ignored. Do not use both options simultaneously. + ## Usage To be able to use the dotenv classes, simply include the main header file: From 9cf61b18fcd925a990be0b997829ed253fc823cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Wed, 21 Jan 2026 10:14:09 +0100 Subject: [PATCH 5/7] Address CodeRabbit AI review feedback - Fix README CMake version mismatch: update from >=3.10 to >=3.16 to match CMakeLists.txt requirement - Fix Windows MSVC import library conflict: when BUILD_BOTH_LIBRARIES is ON, both static and shared libraries would produce cpp_dotenv.lib on Windows. Add IMPORT_SUFFIX "_shared.lib" to the shared library's import library to avoid this conflict on Windows/MSVC. --- CMakeLists.txt | 5 +++++ README.md | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2624a29..49e0468 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -72,6 +72,11 @@ if(BUILD_BOTH_LIBRARIES) target_compile_options(cpp_dotenv_shared PRIVATE ${CPP_DOTENV_COMPILE_OPTIONS}) # Set output name to libcpp_dotenv.so/.dylib (instead of libcpp_dotenv_shared.so) set_target_properties(cpp_dotenv_shared PROPERTIES OUTPUT_NAME cpp_dotenv) + # On Windows (MSVC), the import library would conflict with the static library. + # Add a suffix to the import library name to avoid this conflict. + if(MSVC) + set_target_properties(cpp_dotenv_shared PROPERTIES IMPORT_SUFFIX "_shared.lib") + endif() # Alias for backward compatibility: # When BUILD_BOTH_LIBRARIES is ON, the cpp_dotenv target is an alias to diff --git a/README.md b/README.md index 198f6f1..24a0a63 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ C++ implementation of NodeJS [dotenv](https://github.com/motdotla/dotenv) projec Supported build methods are: -- [CMake](#cmake) (>=3.10) +- [CMake](#cmake) (>=3.16) ### CMake From 45ad9819c2e772b43d5f9f9e13bf9e880656c2ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Wed, 21 Jan 2026 10:52:00 +0100 Subject: [PATCH 6/7] Address Copilot review feedback for PR 1 dotenv.h: - Clarify inline variable syntax with explanatory comment - Add comment explaining why _instance cannot be inline inside class dotenv.cpp: - Rename Dotenv_Type to DotenvClass for better C++ conventions - Fix operator[] to use typedef alias consistently (avoid parsing issues) - Improve comment clarity for the global env variable definition CMakeLists.txt: - Add MSVC support for compiler flags (/W4 /Od /O2) - Improve Windows library naming: use distinct OUTPUT_NAME on MSVC to avoid conflicts between static and shared library .lib files common/libs/antlr4-cpp-runtime/CMakeLists.txt: - Update cmake_minimum_required from 3.10 to 3.16 for consistency --- CMakeLists.txt | 30 +++++++++++++------ common/libs/antlr4-cpp-runtime/CMakeLists.txt | 2 +- include/dotenv.h | 9 ++++-- src/dotenv.cpp | 12 ++++---- 4 files changed, 34 insertions(+), 19 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 49e0468..1bebe33 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,11 +42,21 @@ set(CPP_DOTENV_SRC # Common include directories set(CPP_DOTENV_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include) -# Common compile options -if ("${CMAKE_BUILD_TYPE}" STREQUAL "DEBUG") - set(CPP_DOTENV_COMPILE_OPTIONS -g -Wall -O0) +# Common compile options - handle MSVC vs GCC/Clang +if (MSVC) + # MSVC-specific flags + if ("${CMAKE_BUILD_TYPE}" STREQUAL "DEBUG") + set(CPP_DOTENV_COMPILE_OPTIONS /W4 /Od) + else() + set(CPP_DOTENV_COMPILE_OPTIONS /W4 /O2) + endif() else() - set(CPP_DOTENV_COMPILE_OPTIONS -O3) + # GCC/Clang and other compilers using Unix-style flags + if ("${CMAKE_BUILD_TYPE}" STREQUAL "DEBUG") + set(CPP_DOTENV_COMPILE_OPTIONS -g -Wall -O0) + else() + set(CPP_DOTENV_COMPILE_OPTIONS -O3) + endif() endif() # Build both static and shared libraries if requested @@ -70,12 +80,14 @@ if(BUILD_BOTH_LIBRARIES) ) target_include_directories(cpp_dotenv_shared PUBLIC ${CPP_DOTENV_INCLUDE_DIRS}) target_compile_options(cpp_dotenv_shared PRIVATE ${CPP_DOTENV_COMPILE_OPTIONS}) - # Set output name to libcpp_dotenv.so/.dylib (instead of libcpp_dotenv_shared.so) - set_target_properties(cpp_dotenv_shared PROPERTIES OUTPUT_NAME cpp_dotenv) - # On Windows (MSVC), the import library would conflict with the static library. - # Add a suffix to the import library name to avoid this conflict. + # Set output name. On non-MSVC platforms, both static and shared libraries use + # the same base name "cpp_dotenv". On MSVC, give the shared library a distinct + # base name to avoid conflicts between the static library (.lib) and the + # import library for the shared library (also .lib). if(MSVC) - set_target_properties(cpp_dotenv_shared PROPERTIES IMPORT_SUFFIX "_shared.lib") + set_target_properties(cpp_dotenv_shared PROPERTIES OUTPUT_NAME cpp_dotenv_shared) + else() + set_target_properties(cpp_dotenv_shared PROPERTIES OUTPUT_NAME cpp_dotenv) endif() # Alias for backward compatibility: diff --git a/common/libs/antlr4-cpp-runtime/CMakeLists.txt b/common/libs/antlr4-cpp-runtime/CMakeLists.txt index c208123..e00a12c 100644 --- a/common/libs/antlr4-cpp-runtime/CMakeLists.txt +++ b/common/libs/antlr4-cpp-runtime/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.16) project(antlr4-cpp-runtime VERSION 4.8) set(CMAKE_CXX_STANDARD 17) diff --git a/include/dotenv.h b/include/dotenv.h index 851376a..e20657e 100644 --- a/include/dotenv.h +++ b/include/dotenv.h @@ -35,15 +35,18 @@ namespace dotenv private: + // Declare static members (definitions are inline after the class) static const std::string env_filename; static dotenv _instance; }; - extern dotenv& env; - - // Inline variables defined after class is complete (C++17) + // C++17 inline variable definitions after class is complete + // Note: _instance cannot be inline inside the class due to incomplete type inline const std::string dotenv::env_filename = ".env"; inline dotenv dotenv::_instance; + + + extern dotenv& env; } diff --git a/src/dotenv.cpp b/src/dotenv.cpp index 89585f9..9e55b18 100644 --- a/src/dotenv.cpp +++ b/src/dotenv.cpp @@ -10,12 +10,12 @@ using namespace std; -// Typedef to work around the fact that class name matches namespace name +// Type alias to work around the fact that class name matches namespace name // This is a known C++ limitation when defining out-of-line members -typedef class ::dotenv::dotenv Dotenv_Type; +typedef class ::dotenv::dotenv DotenvClass; -Dotenv_Type& ::dotenv::dotenv::load_dotenv(const string& dotenv_path, const bool overwrite, const bool interpolate) +DotenvClass& ::dotenv::dotenv::load_dotenv(const string& dotenv_path, const bool overwrite, const bool interpolate) { ifstream env_file; env_file.open(dotenv_path); @@ -31,17 +31,17 @@ Dotenv_Type& ::dotenv::dotenv::load_dotenv(const string& dotenv_path, const bool } -auto ::dotenv::dotenv::operator[](const key_type& k) const -> const string +const string DotenvClass::operator[](const key_type& k) const { return getenv(k).second; } -Dotenv_Type& ::dotenv::dotenv::instance() +DotenvClass& ::dotenv::dotenv::instance() { return _instance; } -// Static members are now inline in the header (C++17) +// Define the global 'env' reference. Static members are inline in the header (C++17). ::dotenv::dotenv& ::dotenv::env = ::dotenv::dotenv::instance(); From 3f67461b0c4eef144b65a57cf4711eb595bf5dcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Canna=C3=B2?= Date: Wed, 21 Jan 2026 13:05:40 +0100 Subject: [PATCH 7/7] Add backward compatibility comment for env_filename Address remaining Copilot feedback: env_filename is kept for backward compatibility as external code may reference dotenv::dotenv::env_filename directly. Add explanatory comment to document this. --- include/dotenv.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/dotenv.h b/include/dotenv.h index e20657e..3d786d6 100644 --- a/include/dotenv.h +++ b/include/dotenv.h @@ -36,6 +36,8 @@ namespace dotenv private: // Declare static members (definitions are inline after the class) + // NOTE: env_filename is kept for backward compatibility; external code + // may reference dotenv::dotenv::env_filename directly. static const std::string env_filename; static dotenv _instance;