The following fails to compile.
template <typename... U>
requires requires(U... x) { (std::to_string(x) && ...); }
auto to_string(const std::variant<U...>& value) {
return std::visit([](auto&& value) {
return std::to_string(std::forward<decltype(value)>(value));
}, value);
}
int main() {
std::variant<int, float> v = 42;
std::cout << to_string(v) << std::endl;
}
https://godbolt.org/z/Wvn6E3PG5
If I convert the direct requires expression into a concept though, it works fine.
template<typename T, typename... U>
concept to_stringable = requires(U... u) { (std::to_string(u) && ...); };
template <to_stringable... U>
auto to_string(const std::variant<U...>& value) {
return std::visit([](auto&& value) {
return std::to_string(std::forward<decltype(value)>(value));
}, value);
}
int main() {
std::variant<int, float> v = 42;
std::cout << to_string(v) << std::endl;
}
When you have:
This checks if each individual type satisfies
to_stringable<T>, so it is essentially equivalent to:And with just one argument
Tyour concept is:However, with more than one argument, it looks like:
Which doesn't work because you can't
&&twostd::strings, so the constraint is not satisfied.What you really want to do is fold over a constraint:
... Which gcc doesn't seem to implement properly because of a bug but you can get away with: