MSVC accepts lambda with deleted parameterized ctor while GCC and Clang rejects

Summary

The issue at hand is a lambda expression that is accepted by MSVC but rejected by both GCC and Clang. The lambda expression attempts to initialize a captured variable b with an instance of struct C, which has a deleted parameterized constructor. The standard compliant behavior is the one exhibited by GCC and Clang, which reject the code due to the use of a deleted function.

Root Cause

The root cause of this issue is the incorrect handling of deleted functions by MSVC. The key points are:

  • The struct C has a deleted parameterized constructor C(int) = delete;
  • The lambda expression attempts to initialize the captured variable b with C(3), which requires the use of the deleted constructor
  • MSVC incorrectly accepts the code, while GCC and Clang correctly reject it due to the use of a deleted function

Why This Happens in Real Systems

This issue can occur in real systems when:

  • Legacy code is compiled with different compilers, leading to inconsistent behavior
  • Template metaprogramming is used, which can lead to complex constructor calls that may involve deleted functions
  • Lambda expressions are used to capture variables, which can lead to subtle issues with constructor calls

Real-World Impact

The real-world impact of this issue is:

  • Inconsistent behavior across different compilers, leading to portability issues
  • Subtle bugs that may only be detected when the code is compiled with a different compiler
  • Maintenance challenges due to the need to ensure consistent behavior across different compilers

Example or Code

struct C {
  C(int) = delete;
  C() {}
};

int main() {
  // decltype([b = C(3)](){ return 4;}()) var; // MSVC OK, GCC and Clang reject
  // decltype([C(3)](){ return 4;}()) var2; // accepted by all compilers
  // decltype([b=C(3)](){ return 4;}()) var3; // accepted by MSVC, rejected by GCC and Clang
  return 0;
}

How Senior Engineers Fix It

Senior engineers fix this issue by:

  • Understanding the language standard and the behavior of deleted functions
  • Using compiler flags to enable warnings and errors for deleted functions
  • Testing code with multiple compilers to ensure consistent behavior
  • Refactoring code to avoid the use of deleted functions in lambda expressions

Why Juniors Miss It

Juniors may miss this issue due to:

  • Lack of understanding of the language standard and deleted functions
  • Insufficient testing with multiple compilers
  • Overreliance on a single compiler, leading to portability issues
  • Inadequate code review, which can fail to detect subtle issues with lambda expressions and deleted functions

Leave a Comment