Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't decltype work with overloaded functions?

decltype fails if the function you're calling it on is overloaded, as in this code:

#include <iostream>

int test(double x, double y);
double test(int x, int y);
char test(char x, int y);

int main()
{
  std::cout << decltype(test) << std::endl;

  return 0;
}

Results:

error: decltype cannot resolve address of overloaded function

I understand that this is because decltype can't figure out which function you're trying to get the type of. But why isn't there another way to make this work, like this:

std::cout << decltype(test(double, double)) << std::endl;

or this:

double x = 5, y = 2;
std::cout << decltype(test(x, y)) << std::endl;

Since a function cannot be overloaded simply based on return type, wouldn't passing either datatypes or actual variables to the decltype call be enough to tell it which of the overloads it's supposed to examine? What am I missing here?

like image 452
cf stands with Monica Avatar asked Mar 10 '14 03:03

cf stands with Monica


People also ask

What does Decltype function do in C++?

The decltype type specifier yields the type of a specified expression. The decltype type specifier, together with the auto keyword, is useful primarily to developers who write template libraries. Use auto and decltype to declare a function template whose return type depends on the types of its template arguments.

Is it possible to automatically overload functions?

Function overloading is possible in C++ and Java but only if the functions must differ from each other by the types and the number of arguments in the argument list. However, functions can not be overloaded if they differ only in the return type.


1 Answers

To figure out the type of the function from the type of the arguments you'd pass, you can "build" the return type by using decltype and "calling" it with those types, and then add on the parameter list to piece the entire type together.

template<typename... Ts>
using TestType = decltype(test(std::declval<Ts>()...))(Ts...);

Doing TestType<double, double> will result in the type int(double, double). You can find a full example here.

Alternatively, you might find the trailing return type syntax more readable:

template<typename... Ts>
using TestType = auto(Ts...) -> decltype(test(std::declval<Ts>()...));
like image 97
chris Avatar answered Sep 28 '22 06:09

chris