Skip to content

ADL_ostreamable cannot find operator<< for std::filesystem::path #51

Description

@saki7

Maybe the current implementation cannot find hidden friends?

Activity

  1. added
    bugSomething isn't working
    language-lawyerImplies unclear specification on the C++ standard, or potential misinterpretation/bug on compilers
    on Mar 8, 2026
  2. yaito3014 commented on Mar 13, 2026

    @yaito3014
    Member

    It seems the problem is that the poison-pill overload is declared specifically for std::ostream, not for std::basic_ostream.
    When the ADL_ostreamable finds the two overloads, the poison-pill overload is "more specialized" prioritized than the templated one.

    Current implementation rejects even ADL_ostreamable_v<char>, since the overload is templated one.

  3. saki7 commented on Mar 13, 2026

    @saki7
    MemberAuthor

    Perhaps we don't need poison pill here?

    At the time of initial implementation, I included that poison pill to deselect some bad overloads, but I think we can just make it "properly findable" and just remove the poison pill?

    // Bad global overload; can be avoided by the poison pill
    [[maybe_unused]] std::ostream& operator<<(std::ostream& os, NonStreamable_ns::NonStreamable const&)
    {
    return os << "polluted const&";
    }

    After removing the poison pill and the test cases mentioned above, I think ADL_ostreamable is going to work for any kind of overloaded functions.

  4. saki7 commented on Mar 13, 2026

    @saki7
    MemberAuthor

    By the way, I think it should also be noted that inclusion or nonexistence of some header greatly affects the viability of ADL_ostreamable:

    #include <iris/io_fwd.hpp>
    #include "detect_something_based_on_ADL_ostreamable.hpp"
    #include <string>
    
    // or
    
    #include <iris/io_fwd.hpp>
    #include <string>
    #include "detect_something_based_on_ADL_ostreamable.hpp"

    Just to clarify: these may result in different compile-time result(*), so ADL_ostreamable is extremely fragile. Perhaps it's the reason why it has not been standardized yet, but I still think it should be implemented; otherwise we won't be able to implement operator<< in a derived class in SFINAE-friendly way.

    (*) Mixing these variations in a same program should be UB or IFNDR, if I understand correctly.

  5. yaito3014 commented on Mar 13, 2026

    @yaito3014
    Member

    Perhaps we don't need poison pill here?

    Probably yes. Original intention for poison-pill overload is to deselect bad unconstrained overload which existed in std namespace, not in global namespace.
    Indeed globally pollute the function is bad, but deselecting those is "tier 2" purpose.
    Since we don't have unconstrained operator<< in iris namespace, we can safely remove poison-pill.

  6. saki7 commented on Mar 13, 2026

    @saki7
    MemberAuthor

    Perhaps we don't need poison pill here?

    Probably yes. Original intention for poison-pill overload is to deselect bad unconstrained overload which existed in std namespace, not in global namespace. Indeed globally pollute the function is bad, but deselecting those is "tier 2" purpose. Since we don't have unconstrained operator<< in iris namespace, we can safely remove poison-pill.

    Then I think removing poison poll is the right way to proceed. You may also remove the unit tests quoted above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinglanguage-lawyerImplies unclear specification on the C++ standard, or potential misinterpretation/bug on compilers

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions