boostorg / boostorg/hana

Comparison between compile-time string and std::string behaves unexpectedly

Open
#346 3 comments 1 reaction 0 assignees View on GitHub
Dominant language
C++
Stars
1.9k
Forks
225
PR merge metrics
No merged PRs in 30d

Description

The following code has a very unexpected behavior:

```c++
#include
#include

#define BOOST_HANA_CONFIG_ENABLE_STRING_UDL
#include
#include
using namespace boost::hana::literals;
using namespace std::literals;

int main() {
assert(boost::hana::equal("x"_s, "x"s)); // assertion fails
}
```

The problem here is that since `"x"_s` is a compile-time string (`hana::string`) and `"x"s` is a `std::string`, which have nothing in common (no common type, no conversion, etc.), Hana says they are not equal (instead of giving an error, for example). The rationale is documented in [`Comparable`'s documentation](http://boostorg.github.io/hana/group__group-Comparable.html):

> In the context of programming with heterogeneous values, it is useful to have unrelated objects compare false instead of triggering an error. For this reason, equal adopts a special behavior for unrelated objects of tags `T` and `U` that do not satisfy the above requirements for the cross-type overloads. Specifically, when `T` and `U` are unrelated (i.e. `T` can't be converted to `U` and vice-versa), comparing objects with those tags yields a compile-time false value. This has the effect that unrelated objects like `float` and `std::string` will compare `false`, while comparing related objects that can not be safely embedded into the same super structure (like `long long` and `float` because of the precision loss) will trigger a compile-time assertion. Also note that for any tag `T` for which the minimal complete definition of `Comparable` is not provided, a compile-time assertion will also be triggered because `T` and `T` trivially share the common tag `T`, which is the expected behavior. This design choice aims to provide more flexibility for comparing objects, while still rejecting usage patterns that are most likely programming errors.

This special behavior of comparing `false` for unrelated types usually works as intended, except when it does not. One _possible_ solution would be to check whether `T` and `U` are `Comparable`, and if so, then compare them when writing an algorithm. It _might_ make algorithms more complex to write, although one could provide a helper function that does that.

Thanks to @Quuxplusone for finding this out.

Contributor guide

Open the contributing guide

Research direction

Start with boost/hana/string.hpp and boost/hana/equal.hpp, then read the Comparable documentation linked in the issue. Reproduce the minimal C++ example and determine the intended policy for comparing hana::string with std::string; done requires an agreed behavior and regression coverage for this case.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
devtools
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.