Repository navigation
ADL_ostreamable cannot find operator<< for std::filesystem::path #51
Description
Activity
- addedbugSomething isn't workingSomething isn't workinglanguage-lawyerImplies unclear specification on the C++ standard, or potential misinterpretation/bug on compilersImplies unclear specification on the C++ standard, or potential misinterpretation/bug on compilers
on Mar 8, 2026 It seems the problem is that the poison-pill overload is declared specifically for
std::ostream, not forstd::basic_ostream.
When theADL_ostreamablefinds 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.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?
Lines 22 to 26 in 8104bf7
// 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_ostreamableis going to work for any kind of overloaded functions.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_ostreamableis 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 implementoperator<<in a derived class in SFINAE-friendly way.(*) Mixing these variations in a same program should be UB or IFNDR, if I understand correctly.
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
stdnamespace, not in global namespace.
Indeed globally pollute the function is bad, but deselecting those is "tier 2" purpose.
Since we don't have unconstrainedoperator<<inirisnamespace, we can safely remove poison-pill.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
stdnamespace, not in global namespace. Indeed globally pollute the function is bad, but deselecting those is "tier 2" purpose. Since we don't have unconstrainedoperator<<inirisnamespace, 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.
Maybe the current implementation cannot find hidden friends?