Почему разрешение перегрузки не может решить, какую версию перегруженной функции инициализировать объект std :: function? - PullRequest
0 голосов
/ 03 мая 2020

У меня есть этот пример о std::function:

int add(int x, int y, int z) {return x + y + z;}
int add(int a, int b) {return a + b;}

int main()
{
    std::function<int(int, int)> fn = add; // error

    int(*pfn)(int, int) = add; // OK
    fn = pfn; // ok  fn is bound to add(int, int)
    std::cout << fn(5, 7) << std::endl; // 12

}
  • Почему разрешение перегрузки не решает, какая версия add при инициализации fn, но может инициализировать указатель на функцию pfn?

  • Существует ли обходной путь, вместо использования указателя функции, чтобы решить, какая версия перегруженной функции используется в качестве инициализатора для объекта std::function?

Ответы [ 2 ]

1 голос
/ 03 мая 2020

Почему разрешение перегрузки не определяет, какая версия add при инициализации fn, но способно инициализировать указатель функции pfn?

Из-за перегрузки разрешение выполняется при инициализации указателя функции (например, pfn) в зависимости от типа указателя функции.

Во всех этих контекстах функция, выбранная из набора перегрузки, имеет вид функция, тип которой соответствует указателю на функцию, ссылке на функцию или указателю на тип функции-члена, ожидаемый target : инициализируемый объект или ссылка, левая часть назначения, функция или параметр оператора, тип возвращаемого значения функции, целевой тип приведения или тип параметра шаблона, соответственно.

С другой стороны, такое разрешение перегрузки не происходит при инициализации std::function, который имеет шаблон конструктора и параметр шаблона должен быть выведен из функции аргумент; компилятор не может выбрать один из них для вычета.

В качестве обходного пути вы можете применить static_cast, чтобы явно указать нужную перегрузку.

static_cast может также использоваться для устранения неоднозначности перегрузок функций путем выполнения преобразования функции в указатель в специфицированный c тип

std::function<int(int, int)> fn = static_cast<int(*)(int, int)>(add);
0 голосов
/ 03 мая 2020

В случае указателя на функцию в C ++ есть специальное правило, разрешающее своего рода поиск во времени. Он может выполнять разрешение перегрузки для имени, основываясь на том, что вы собираетесь назначить / инициализировать имя.

Это в основном хак, встроенный в язык (правила в [over.over] ).

Никакая другая часть языка не работает таким образом. Например, если новички часто ожидают, что после написания float x = 1/2 значение x будет 0.5, мы должны объяснить, что факт инициализации float не имеет отношения к типам или вычислениям выражение 1/2.

Этот хак не был расширен до std::function. Предположительно, это потому, что добавление хаков - это плохо, и потому что это не нужно для этого случая. Почему бы нет? Потому что вы все еще можете развернуть хак косвенно с помощью static_cast на RHS вашей std::function инициализации:

std::function<int(int, int)> fn = static_cast<int(*)(int, int)>(add);

… и есть ваш обходной путь.

...