According to en.cppreference.com in convertible_to:
The concept convertible_to<From, To> specifies that an expression of the same type and value category as those of std::declval() can be implicitly and explicitly converted to the type To, and the two forms of conversion are equivalent.
I Understood this to mean that convertible_to concept will identify convertible_to<U, V> as satisfied if U has a member explicit operator V(). Even if the operator is explicit and not an implicit operator.
However I have discovered that this is not the case in msvc.
The following code fails to compile due to the static assert:
#include <concepts>
#include <iostream>
class ExplictClass
{
public:
inline explicit operator int() const
{
return 5;
}
};
int main()
{
static_assert(std::convertible_to<ExplictClass, int>, "Explicit not convertible?"); // Fails here, concept not satisfied.
}
Is this a misunderstanding I have about the concept std::convertible_to, an error in the code, or error in en.cppreference.com, or Non-conformance of msvc v19.
Attached link to compiler explorer with above code using x64 msvc v19.latest
EDIT:
The actual need for convertible_to was to generate a to_string function template that works well with castable types declared as so:
template<class T>
std::string to_string(T val)
{
std::ostringstream stream;
stream << val;
return stream.str();
}
template<Convertible<std::string> T>
std::string to_string(T val)
{
return static_cast<std::string>(val);
}
Here I want types like const char*, char*, a type like ExplicitClass (with explicit operator std::string) all to use the second method, with the first method being a fallback option
std::convertible_torequires both implicit and explicit conversion1). This can be seen in the definition:1) Note: implicit convertibility almost always implies explicit convertibility
Your
ExplicitClassonly has an explicit conversion toint, meaning that you can writeExplicitClass(0), but it would not be possible to writeExplicitClass e = 0;, which requires an implicit conversion.If you want a concept which tests whether
ExplicitClasscan be explicitly converted toint, you have two options:A - Use just the explicit part of
std::convertible_toB: Use
std::constructible_fromNote that
std::constructible_from<To, From>will test whether:std::is_nothrow_destructible_v<To>, andTo obj(From)is well-formed, which is a weaker form ofstatic_cast<To>(From)(both are direct initializaton, but onlystatic_castcan downcast pointers fromBase*toDerived*, among other differences)This means that
std::constructible_fromisn't equivalent to astatic_cast, but it will do exactly what you want for class types likeExplicitClass.