I'm encountering an issue where the compiler seems unable to implicitly deduce the template argument T when I try to call largest() with a std::vector<T>. Explicitly specifying T (e.g., largest<std::string>(myVector)) works, but I'm seeking a deeper understanding of why this is necessary.
std::string largest(std::span< std::string > elements);
template <typename T> std::optional<T> largest(std::span<T> elements);
int main(int argc, char* argv[]) {
std::vector< std::string > elements { "A", "B", "C", "D" };
std::cout << largest(elements) << std::endl;
std::vector<int> integers { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
// std::cout << largest(integers) << std::endl; COMPILER CAN'T RESOLVE OVERLOAD
// correct version
std::optional<int> maximum { largest<int>(integers) };
if(maximum.has_value())
std::cout << maximum.value() << std::endl;
return 0;
}
std::string largest(std::span< std::string > elements) {
std::string maximum {};
for(const auto& element : elements) {
if(auto ordering { element <=> maximum }; ordering == std::strong_ordering::greater)
maximum = element;
}
return maximum;
}
template <typename T> std::optional<T> largest(std::span<T> elements) {
if( elements.empty() ) return std::nullopt;
T maximum {};
for(const auto& element : elements) {
if(auto ordering { element <=> maximum }; ordering == std::strong_ordering::greater)
maximum = element;
}
return maximum;
}
Yes, for it to be possible to deduce
T, you'd have to supply astd::spanover "something". The match must be exact for deduction to work and avector<T>and aspan<T>are not the same type and it doesn't help that aspan<T>has a converting constructor that lets it be created from avector<T>.You could however make it simpler by just accepting any forward range. To simplify it further, you could also use a standard algorithm to find the element with the maximum value.
Example: