ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • boost::asio 완료 핸들러에 제네릭 람다 사용 시 있었던 문제
    프로그래밍/c++ - boost::asio 2015. 9. 17. 17:34
    반응형

    컴파일 타임에 오류가 나는데 잡기가 어려웠다. 문제의 코드를 보자.

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
      tcp_socket.async_receive(
        buffer_write_section,
        receive_complete_handler);
        [this](const auto& error, size_t bytes_transferred)
      {
        if (error)
        {
          this->on_error(error);
          return;
        }
     
        this->receive_buffer.commit(bytes_transferred);
     
        // 버퍼의 읽기 부분을 추출.
        auto read_section = this->receive_buffer.data();
        auto read_data = asio::buffer_cast<const char*>(read_section);
        auto read_size = asio::buffer_size(read_section);
     
        this->on_receive();
      } // lambda
      ); // async_receive
    cs

     

    코드는 문제가 없게 보였다. 하지만 컴파일 오류가 발생했고 람다 코드에 주석을 하나씩 달아보며 뭐가 문제인지를  찾아봤다.

    ...

    //버퍼의 읽기 부분을 추출

    부분에 있는 코드를 지우니 문제 없이 빌드가 되더라. 그러면 buffer_cast 부분을 잘못 사용한 건가? 래퍼런스에는 저렇게 사용하는 맞던데? 라고 생각해서 다른 부분을 고쳐봤다.

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
      tcp_socket.async_receive(
        buffer_write_section,
        receive_complete_handler);
    // ** auto가 아닌 명시적 람다로 바꾸었다!
        [this](const boost::system::error_code& error, size_t bytes_transferred) 
      {
        if (error)
        {
          this->on_error(error);
          return;
        }
     
        this->receive_buffer.commit(bytes_transferred);
     
        // 버퍼의 읽기 부분을 추출.
        auto read_section = this->receive_buffer.data();
        auto read_data = asio::buffer_cast<const char*>(read_section);
        auto read_size = asio::buffer_size(read_section);
     
        this->on_receive();
      } // lambda
      ); // async_receive
    cs

     

    이렇게 바꾸니까 빌드가 되네? 그럼 buffer_cast 잘못된 아니었구나..

    근데 vs2015 제네릭 람다를 지원하는데?...

     

    해서..

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
      tcp_socket.async_receive(
        buffer_write_section,
        receive_complete_handler);
        [this](const auto& error, size_t bytes_transferred)->void // ** 반환형을 명시적으로 지정했다.
      {
        if (error)
        {
          this->on_error(error);
          return;
        }
     
        this->receive_buffer.commit(bytes_transferred);
     
        // 버퍼의 읽기 부분을 추출.
        auto read_section = this->receive_buffer.data();
        auto read_data = asio::buffer_cast<const char*>(read_section);
        auto read_size = asio::buffer_size(read_section);
     
        this->on_receive();
      } // lambda
      ); // async_receive
     

    cs


    .. 이렇게 하니까 빌드가 되더라.

    아마 return; 부분 때문에 컴파일러가 반환형을 잘못 추측해서 발생한 아닐까 싶다.

     

    증거로 코드에서 반환형 부분을 void 아닌 auto 지정하면 오류가 발생한다.


    * vs만의 문제일지는 모르겠다. 하지만 이런 경우도 있을 수 있다는 걸 알았다.

    반응형
Designed by Tistory.