type - lambda函數c++




C++ 11是否要求將此lambda聲明為可變? (2)

這不是關於lambdas的。

#include <functional>
#include <cstdlib>

int main() {
  const auto x = std::bind(std::puts, "hello");
  x();
}

這被GCC接受,但被MSVC拒絕。

關於這是否有效,IMO還不清楚這個標準。 std::bind的返回值g有一個未指定的返回類型, g(...)有效並根據g的cv限定符定義,但標準實際上並沒有說任何operator()必須可以為const限定的對像或引用調用。 它強烈暗示這是有效的,因為否則對g的cv-qualifiers的引用似乎沒用,但它實際上並不認為它是有效的。

因此,我認為MSVC的行為不是標準作者的意圖,但它可能符合標準的要求。

考慮一下這個C ++ 11代碼:

#include <functional>
#include <cstdlib>

template <typename F>
void test(F &&f) {
    auto foo = [f]() {
        f();
    };
    foo();
}

int main() {
    test(std::bind(std::puts, "hello"));
    return 0;
}

GCC和Clang接受此作為有效的C ++ 11代碼,但Visual Studio 2013要求將lambda聲明為可變( auto foo = [f]() mutable { ... } )。 否則我收到此錯誤:

錯誤C3848:類型為' const std::_Bind<true,int,int (__cdecl *const )(const char *),const char (&)[6]> cdecl const std::_Bind<true,int,int (__cdecl *const )(const char *),const char (&)[6]> '的表達式會丟失一些const-volatile限定符以便調用' int std::_Bind<true,int,int (__cdecl *const )(const char *),const char (&)[6]>::operator ()<>(void) '

Visual Studio是否正確拒絕此代碼而沒有可變,或者它是否有效C ++ 11?

(如果你將std::bind(std::puts, "hello")改為std::bind(std::exit, 0) Curiously Clang拒絕代碼std::bind(std::exit, 0)顯然是因為它認為noreturn使函數類型不同;我'我很確定這是一個錯誤。)


這看起來像是bind的Visual Studio實現中的一個錯誤,只返回一個只有非const函數調用操作符的類型。 它應該返回一個類型,它將所有函數調用轉發給綁定的函數對象,而不管它自己的cv資格。

為了總結C ++ 11 20.8.9.1.2中相當不透明的語言,對bind結果的函數調用應該轉發給綁定的函數對象,因此如果允許對該對象進行調用則應該允許。 因此,如果綁定的函數對像在const不可調用則會出錯; 但在這裡,作為一個函數指針,無論cv資格如何,它都是可調用的。





language-lawyer