Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Variadic Max function in C++20

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:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

#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 Max function in […] ?

Your Max function can maximize the simplicity by

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;
    }
}

See live demo in godbolt.org


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;
}

See live demo in godbolt.org

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...>
{
    // ....
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading