Skip to content

Consider putting the user-defined literals in a namespace #1682

Closed

Description

If I'm not mistaken, the user-defined literals are outside the nlohmann namespace. This means if the header is included twice, there will be a conflict. My use-case (or rather the library I'm contributing to) looks something like this:

  // Remove the include guards because third-parties may have included their own
  // version of nlohmann::json. 
  #undef NLOHMANN_JSON_HPP
  #undef NLOHMANN_JSON_FWD_HPP
  
  #define nlohmann library_internal_nlohmann_3_4_0
  #include <nlohmann/json.hpp>

The idea is that because the namespace is renamed to something that will not conflict, the library can be included multiple times. Previously, we would grab nlohmann_json as an external project and patch the user-defined literals out; however since we are moving to using find_package only, this is not possible (or would be ugly).

There is a downside to this: it would obviously break backwards compatibility. However, including it would be simple if it looked something like this:

namespace nlohmann {
inline namespace literals {
// ... define literals here
}
}

Then in user-code:

using namespace nlohmann::literals; // does not pollute global namespace

I am only 50/50 for this idea and would like to hear your thoughts.

Activity

  1. nlohmann commented on Jul 23, 2019

    @nlohmann
    Owner

    I understand the issue, and #1539 could be part of the solution. However, removing the literal operator from the default public API would be a breaking change, right?

  2. MikeGitb commented on Jul 29, 2019

    @MikeGitb

    Personally, I think putting UDLs into the global namespace (in a header) is a no-go anyway. Especially, if they have very generic names like _json.

  3. stale commented on Aug 28, 2019

    @stale

    This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

  4. added
    state: stalethe issue has not been updated in a while and will be closed automatically soon unless it is updated
    on Aug 28, 2019
  5. MikeGitb commented on Aug 28, 2019

    @MikeGitb

    I don't think this should be closed until a decision for or against is made.

  6. removed
    state: stalethe issue has not been updated in a while and will be closed automatically soon unless it is updated
    on Aug 28, 2019
  7. t-b commented on Aug 28, 2019

    @t-b
    Contributor

    @MikeGitb I'm (random json.hpp user) in favour for putting the UDLs into their own namespace. fmt does that as well, see https://fmt.dev/latest/api.html?highlight=literal#literal-based-api.

  8. MikeGitb commented on Aug 28, 2019

    @MikeGitb

    So am I

  9. t-b commented on Aug 28, 2019

    @t-b
    Contributor

    How about the following changes:

    • Move UDLs into nlohmann::json::literals namespace
    • Introduce JSON_LITERALS_SEPARATE define to choose if UDLs are in the global namespace (undefined, default) or not.

    So something like

    #ifndef JSON_LITERALS_SEPARATE
    using namespace nlohmann::json::literals;
    #endif // JSON_LITERALS_SEPARATE

    in the global namespace.

    Edited: Thanks @MikeGitb

  10. MikeGitb commented on Aug 28, 2019

    @MikeGitb

    I think you have a typo or something like that in your snippet.
    That will put the UDLs unconditionally into the global namespace.

  11. stale commented on Sep 27, 2019

    @stale

    This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

  12. added
    state: stalethe issue has not been updated in a while and will be closed automatically soon unless it is updated
    on Sep 27, 2019
  13. 1 remaining item

  14. removed
    state: stalethe issue has not been updated in a while and will be closed automatically soon unless it is updated
    on Jul 23, 2022
  15. added this to the Release 3.11.0 milestone on Jul 23, 2022
  16. falbrechtskirchinger commented on Jul 24, 2022

    @falbrechtskirchinger
    Contributor

    #3590 doesn't fix this issue. I propose we follow the standard library approach to the letter: https://en.cppreference.com/w/cpp/chrono/operator%22%22h#Notes

    NLOHMANN_JSON_NAMESPACE_BEGIN
    inline namespace literals {
    inline namespace json_literals {
    // define UDLs here
    }
    }
    NLOHMANN_JSON_NAMESPACE_END

    Additionally, introduce the macro JSON_USE_GLOBAL_UDLS which restores the current behavior.

    #if JSON_USE_GLOBAL_UDLS
    using namespace nlohmann::literals::json_literals;
    #endif

    Edit: Removed the unnecessary using namespace pointed out by @MikeGitb here and in PR #3605.

  17. MikeGitb commented on Jul 24, 2022

    @MikeGitb

    If you are already using inline namespaces, you don't need the using namespace literals::json_literals; do you? The reason the linked cppreference.com article mentions a using literals::chrono_literals is to import the litterals into a sibling namespace (std::chrono) and not just in std.

  18. falbrechtskirchinger commented on Jul 24, 2022

    @falbrechtskirchinger
    Contributor

    You're right. I'll apply the change when I can.

  19. removed this from the Release 3.11.0 milestone on Jul 30, 2022
  20. self-assigned this
    on Jul 31, 2022
  21. added this to the Release 3.11.0 milestone on Jul 31, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

    ⌂ 换网址