Despite, the fact, we have std::max, I wanted to try if it is possible to make a Max version which takes variadic arguments and call the Max recursively for finding the max element.
I saw similar posts in stack overflow, but those are old and most of them using std:: max inside. Since I have specific error + using newer compiler, this post is not duplicate easily.
Following is the code I have written:
#include <iostream>
#include <string>
#include <format>
using namespace std::string_literals;
template <typename T>
constexpr T Max(T&& value)
{
return value;
}
template <typename T, typename... Ts>
constexpr T Max(T&& value, Ts&&... args)
{
const T maxRest = Max(args...);
return (value > maxRest) ? value : maxRest;
}
int main()
{
std::cout << std::format("Maximum integer: {}\n", Max(1));
std::cout << std::format("Maximum integer: {}\n", Max(5, 2, 10, 6, 8));
std::cout << std::format("Maximum integer: {}\n", Max("string1", "string2"s)); // error in this line!!
std::cout << std::format("Maximum double: {}\n", Max(3.14, 1.23, 2.56, 0.98));
return 0;
}
For which I am getting:
main.cc(79, 21) : error C2440 : 'initializing' : cannot convert from 'std::string' to 'const char (&)[8]'
main.cc(79, 21) : message: Reason: cannot convert from 'std::string' to 'const char [8]'
main.cc(79, 21) : message: No user - defined - conversion operator available that can perform this conversion, or the operator cannot be called
main.cc(87, 55) : message: see reference to function template instantiation ‘T Max<const char(&)[8],std::string>(T,std::string &&)’ being compiled
with
[
T = const char(&)[8]
]
I think the error is coming from the function call: Max("string1", "string2"s));. I do not know, how can to resolve this?
Likewise, I am also feeling that I am writing more to achieve this Max function in C++20. Does anybody have any suggestion to make the two Max functions in to one.
>Solution :
Likewise, I am also feeling that I am writing more to achieve this
Maxfunction in c++20 […] ?
Your Max function can maximize the simplicity by
-
Having abbreviated function template (Since c++20) declaration, and
-
The compile time branching with
if constexpr(since c++17).
constexpr auto Max(auto const& value, auto const&... args)
{
if constexpr (sizeof...(args) == 0u) // Single argument case!
return value;
else // For the Ts...
{
const auto max = Max(args...);
return value > max ? value : max;
}
}
I think the error is coming from the function call:
Max("string1", "string2"s));.
I do not know, how can to resolve this.
When you call Max("string1", "string2"s)), the compiler deduces the T (i.e. return type), to be
const char[8], that is the type of the first argument(i.e. "string1").However, the second argument is a std::string (i.e. "string2"s). Now for the line :
const T maxRest = Max(args...);
this std::string must be now implicitly convertible to const char [8].This is not viable, and hence the compiler produces a type mismatch error.
To fix the issue, you can simply let the compiler deduce the type for you; That means, instead of defining or assuming the
the return type will be always T, use auto so that compiler can deduce the type for you.
template <typename T, typename... Ts>
constexpr auto Max(T const& value, Ts const&... args)
// ^~~~ ---> Simply 'auto'
{
const auto maxRest = Max(args...);
// ^~~~ ---> Simply 'auto'
return (value > maxRest) ? value : maxRest;
}
Alternatively you could also use the std::common_type_t
for defining the return type.
#include <type_traits> // std::common_type_t
template <typename T, typename... Ts>
constexpr auto Max(T const& value, Ts const&... args)
-> std::common_type_t<T, Ts...>
{
// ....
}