Почему std :: bind принимает больше аргументов, чем возможно для связанной функции? - PullRequest
1 голос
/ 22 мая 2019

Мне было интересно узнать больше о поведении std::bind() с функциями-членами, и я подумал, что для MSVC было бы странно скомпилировать следующий код, когда никакой другой компилятор, который я пробовал, не смог бы.Неправильно ли MSVC компилировать это?

Я пробовал GCC, CLang и некоторые другие второстепенные компиляторы в проводнике компилятора рядом с MSVC: https://godbolt.org/z/DNtP-o

Только MSVC будет компилировать это:

#include <functional>

struct S{
    void f(int){}
};

int main(){
    S s;
    auto binding = std::bind(&S::f,s, 5,3);

    return 0;
}

Это ошибки, которые я получаю при компиляции с 'x86-64 clang 8.0.0':

ошибка: сбой static_assert из-за требования 'integra_constant::значение ?sizeof ... (_ BoundArgs)> = integra_constant:: value + 1: sizeof ... (_ BoundArgs) == integra_constant:: value + 1 '"Неверное количество аргументов для указателя на член"

ошибка: не найдена соответствующая функция для вызова' bind '

1 Ответ

2 голосов
/ 22 мая 2019

Ни один из компиляторов здесь не прав, поскольку программа имеет неопределенное поведение.

Обратите внимание, что MSVC, конечно, выдает ошибки, если вы на самом деле пытаетесь вызвать связанный функтор.Таким образом, вопрос довольно академичен, поскольку в реальной программе, использующей std::bind для создания чего-то, что никогда не может быть вызвано ни при каком пути кода, это не очень полезно.

C ++ 17 [func.bind.bind] / 2 говорит:

Требуется: ... INVOKE (fd, w_1, w_2, ..., w_N) должно быть допустимым выражением для некоторых значений w_1, w_2,... w_N, где N имеет значение sizeof...(bound_args)....

Но это требование к коду, использующему стандартную библиотеку, а не к реализациям (компиляторам и / или библиотекам), и ничто не говорит о том, что реализации должны диагностировать нарушение.Нарушение Требуется: параграф является неопределенным поведением, если не указано иное.

Так что способность g ++ и clang ++ (при использовании libstdc ++) замечать проблему при вызове std::bind просто приятнаБонус за качество реализации.

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

#include <functional>

struct X {
    void operator()() const;
    void operator()(int) const;
};

void f() {
    auto func = std::bind(X{}, 2, 3, 4);
    static_cast<void>(func);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...