cant call a template function with auto return type in main

#include "iostream"
#include "string"
using std::cout, std::cin, std::endl, std::string;
template <typename T, typename U>
auto max(T x, U y);

int main(){
cout << max(5, 6.5) << endl;
return 0;
}
template <typename T, typename U>
auto max(T x, U y) {
/**
* @brief this is a template function that returns the maximum of two values
*/
return (x > y) ? x : y;
}

hi guys, i want to know why is this not working?, but if change the return type from auto to one of the template type it works well. i know i can put the function ahead of the main function but. here is the error code which sounds reasonable error: use of 'auto max(T, U) [with T = int; U = double]' before deduction of 'auto'
The compiler must know the return type when compiling the function call.
Last edited on
I wonder if it's possible to use template incantations to make max(6.5, 4) return a double, and make max(5, 3.3) return an int. I assume not.

Or maybe it's possible to have max<6.5, 4>() return a double, and max<5, 3.3>() return an int? I doubt it but maybe.

edit: off-topic, but I got the compiler to say "sorry" to me :o
main.cpp:26:23: error: sorry, non-type template argument of type 'double' is not yet supported
        Timer<Day, 8, 7.7> timer2;
                      ^
1 error generated.

(was modifying https://stackoverflow.com/a/6531158 to try and do compile-time comparisons)

I forgot that you can't use floats as non-type template arguments.
Last edited on
I forgot that you can't use floats as non-type template arguments.
You can, since C++20:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
template <auto A, auto B> 
  constexpr auto my_min() 
  { 
    if constexpr (A < B) return A; else return B; 
  }

int main()
{
    auto m1 = my_min<1.0, 2>();
    auto m2 = my_min<2.0, 1>();

    static_assert(std::is_same_v<decltype(m1), double>);
    static_assert(std::is_same_v<decltype(m2), int>);
}


I wonder if it's possible to use template incantations to make max(6.5, 4) return a double,

If you write this
1
2
3
4
5
6
constexpr auto my_min(auto a, auto b) 
{ 
  if constexpr (a < b) return a; else return b; 
}
// ...
my_min(6.5, 4);

You will get a compiler error because those parameters a and b aren't constant expressions.

There are tricks to work around this problem. For example, since C++17 this will suffice:
1
2
3
4
5
6
constexpr auto my_min(auto a, auto b) 
{ 
  if constexpr (a() < b()) return a(); else return b(); 
}
// ...
my_min([]{ return 6.5; }, []{ return 4; }); // returns int 


The key here is that each lambda's operator() is a constexpr function. There are other tricks in the same vein, but as far as I know, you always have to write something different than 6.5, even if it's SOME_MACRO(6.5) instead.
Last edited on
I think it is interesting that implicit type upgrading doesn't happen with templates. Take the template out and it works just fine.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>


using std::cout;


int main(){

int a = 5;
double b = 6.5;
cout << (a > b ? a : b);

return 0;
}
Last edited on
I think it is interesting that implicit type upgrading doesn't happen with templates. Take the template out and it works just fine.

I'm not totally sure what you mean, but it works fine with templates too, provided the syntax errors are fixed:
1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
template <typename T, typename U>
  auto max(T x, U y) 
  {
    return (x > y) ? x : y;
  }

int main()
{
  std::cout << ::max(5, 6.5) << '\n';
}
Putting code tags on the OP's code, as well as a bit of judicious reformatting, makes it a bit easier to notice what's going on:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include "iostream"

template <typename T, typename U>
auto max(T x, U y);

int main( )
{
   std::cout << max(5, 6.5) << '\n';
}

template <typename T, typename U>
auto max(T x, U y)
{
   return (x > y) ? x : y;
}

Templates are a bit of an odd duck when it comes to declaring and defining a template function. The entire body of the template must be visible to the compiler before the function can be used. A template can't have separate declarations and definitions as if it were a normal non-template function. Visual Studio 2022 has this error for the OP's code.
error C3779: 'max': a function that returns 'auto' cannot be used before it is defined

Rewrite the template so it is declared and defined before it is used in main and *POW!* It works!
1
2
3
4
5
6
7
8
9
10
11
12
#include "iostream"

template <typename T, typename U>
auto max(T x, U y)
{
   return (x > y) ? x : y;
}

int main( )
{
   std::cout << max(5, 6.5) << '\n';
}

http://coliru.stacked-crooked.com/a/1e32b1d56881871e

If a template function were to be included in a header file the entire template function would have to be in the header, not possible to be split between a header and a separate source translation unit as can be done with non-template functions.
Last edited on
Topic archived. No new replies allowed.