Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing 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 that takes variadic arguments and calls the Max recursively for finding the max element.

I saw similar posts in stack overflow, but those are old and most of them use std::max inside. Since I have a specific error and using a newer compiler, this post is not duplicated 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 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 into one?
like image 467
MyClass Avatar asked May 13 '26 11:05

MyClass


1 Answers

Likewise, I am also feeling that I am writing more to achieve this Max function in c++20 [...]?

As extension to the other answer, using fold expressions, the Max can be made non-recursive as well.

#include <type_traits> // std::common_type, std::remove_cvref
#include <functional>  // std::greater

template<typename... T>  // common type helper
using CommonType = std::common_type_t<std::remove_cvref_t<T>...>;

constexpr auto Max(auto const& value, auto const&... args)
{
    CommonType<decltype(value), decltype(args)...> maxVal = value;

    return sizeof...(args) == 0u ? maxVal 
        : (((maxVal = std::greater{}(args, maxVal) ? args : maxVal), ...)
            , maxVal);
}

Live demo in godbolt.org


However, for the case of consecutive string literals, that requires some addition:

template<typename... T>  // common type helper
using CommonType = std::common_type_t<std::remove_cvref_t<T>...>;

// For string literals comparison.
constexpr auto handleStrLiterals(auto const& t)
{
    if constexpr (std::is_convertible_v<decltype(t), std::string_view>)
            return std::string_view{ t };
    else    return t;
};

constexpr auto Max(auto const& value, auto const&... args)
{
    CommonType<decltype(handleStrLiterals(value)), decltype(args)...>
        maxVal = handleStrLiterals(value);
    return sizeof...(args) == 0u ? maxVal 
        : (((maxVal = std::greater{}(args, maxVal) ? args : maxVal), ...)
            , maxVal);
}

Live demo in godbolt.org

like image 94
JeJo Avatar answered May 16 '26 02:05

JeJo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!