Unexpected behavior when choosing the best sequence of implicit conversion
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
i have follow expample:
https://godbolt.org/z/vo1q4vdqd
class
```cpp
template
struct Variant {
Variant()=default;
Variant(const Variant&);
Variant(Variant&&);
template
Variant(T&&);
};
```
and class
```cpp
struct S1 {
public:
S1(const char*);
S1(const S1&);
S1(S1&&);
operator Variant() const;
};
```
when passing class `S1` to a function that accepts the `Variant` class, the choice of conversion sequence appears non-obvious and inconsistent.
with `VER 1` this results in `T constructor`, but with `VER 3` this results in `operator Variant`...
```cpp
#if VER == 1
S1 j = "";
take_by_ref(j);
take_by_rref(j);
take_by_value(j);
#endif
#if VER == 3
const S1 j = "";
take_by_ref(j);
take_by_rref(j);
take_by_value(j);
#endif
```
these options differ only in the `const` qualifier of the source object of the conversion sequence.
`S1::operator Variant() const` -- is the _const_-annotation member function and can be used by either const-object or non-const-object.
Why do these code variants choose different conversion paths depending only on the constancy of the source object of the conversion sequence?
https://eel.is/c++draft/over.match.best#general-2 is then closer to choosing in each of the variants the conversion sequence using `operator Variant()`:
> [(2.13)](https://eel.is/c++draft/over.match.best#general-2.13)
> F1 is generated from a non-template constructor and F2 is generated from a constructor template[.](https://eel.is/c++draft/over.match.best#general-2.sentence-1)
Replacing a Variant _template-constructor_ with a _non-template-constructors_ will produce ambiguous results.
other example with _consteval_ functions:
https://godbolt.org/z/Kh9KevezK
This case was born out of a discussion of the https://github.com/nlohmann/json/issues/5066
Contributor guide
Research direction
No repository file or test is named. Start by reproducing the VER 1 and VER 3 Godbolt examples, then read the linked [over.match.best] standard wording and compare the constructor-template and conversion-operator candidates; done means establishing whether the differing conversion paths conform to the standard and identifying the appropriate LLVM component or resolution.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 30/100