0

I'm trying to create aliases for std::min and std::max functions based on this answer, but if I try the following code:

#include <algorithm>
namespace math
{
   template< typename T >
   constexpr auto Max = std::max< T >;
}

and try to run such example:

constexpr int a = 2;
constexpr int b = 3;
constexpr int max = math::Max( a, b );

I get this error:

error C3245: 'math::Max': use of a variable template requires template argument list

What is the best way in modern C++ to do this correctly?

pmakal
  • 69
  • 1
  • 6
  • 4
    Specific issues here aside, aliasing a standard library function with a function pointer like this has unspecified behavior and so isn't guaranteed to work at all. Similarly you shouldn't assume that it is permitted by other libraries either if they don't make this explicit, since it limits how they can change overload sets of the function. Write a function (template) forwarding arguments to `std::max` instead if you really need this. – user17732522 Jan 15 '23 at 15:10
  • 2
    No errors when compiling the shown code with gcc 12. Unable to reproduce. – Sam Varshavchik Jan 15 '23 at 15:11
  • 5
    @Makal What Sam Varshavchik is implying here is that the code you are showing _never_ produces errors. The error will occur only if you actually try to use the variable template somewhere, which your shown code is not trying to do. Show the exact [mre] that produces the exact error message in full. – user17732522 Jan 15 '23 at 15:15
  • @user17732522 I updated the question. Also can you please share some link that would confirm what you said earlier: "aliasing a standard library function with a function pointer like this has unspecified behavior and so isn't guaranteed to work at all"? – pmakal Jan 15 '23 at 15:29
  • 1
    https://stackoverflow.com/questions/55687044/can-i-take-the-address-of-a-function-defined-in-standard-library – user17732522 Jan 15 '23 at 15:35
  • I wouldn't do this at all. Libraries should add new functionality, not be shallow wrappers. – HolyBlackCat Jan 15 '23 at 15:52
  • @HolyBlackCat Sometimes good shallow wrappers make life much easier by decreasing the amount of a boilerplate code. – Evg Jan 15 '23 at 15:54
  • @Evg Then they're not shallow. OP's one would be shallow if it worked. – HolyBlackCat Jan 15 '23 at 15:57

2 Answers2

1

Perhaps this bleeding-edge-modern, law-abiding, namespace-respecting, argument-forwarding function alias construct can work for you.

#define FUNCTION_ALIAS(from, to) \
   decltype(auto) to(auto&& ... xs) \
     { return from(std::forward<decltype(xs)>(xs)...); }

FUNCTION_ALIAS(std::max, Max)
n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
0

One possible solution is to introduce a function object:

struct Max_ {
    template<class T>
    constexpr T operator()(const T& a, const T& b) const {
        return std::max(a, b);
    }
};

inline constexpr Max_ Max = {};

Then you can do

std::cout << Max(4, 5); // prints 5
Evg
  • 25,259
  • 5
  • 41
  • 83