Lambda의 명시 적 반환 유형


93

이 코드 (VS2010)를 컴파일하려고하면 다음 오류가 발생합니다. error C3499: a lambda that has been specified to have a void return type cannot return a value

void DataFile::removeComments()
{
  string::const_iterator start, end;
  boost::regex expression("^\\s?#");
  boost::match_results<std::string::const_iterator> what;
  boost::match_flag_type flags = boost::match_default;
  // Look for lines that either start with a hash (#)
  // or have nothing but white-space preceeding the hash symbol
  remove_if(rawLines.begin(), rawLines.end(), [&expression, &start, &end, &what, &flags](const string& line)
  {
    start = line.begin();
    end = line.end();
    bool temp = boost::regex_search(start, end, what, expression, flags);
    return temp;
  });
}

람다에 'void'반환 유형이 있음을 어떻게 지정 했습니까? 또한 람다에 'bool'반환 유형이 있음을 어떻게 지정합니까?

최신 정보

다음이 컴파일됩니다. 누군가가 왜 컴파일되고 다른 사람은 그렇지 않은지 말해 줄 수 있습니까?

void DataFile::removeComments()
{
  boost::regex expression("^(\\s+)?#");
  boost::match_results<std::string::const_iterator> what;
  boost::match_flag_type flags = boost::match_default;
  // Look for lines that either start with a hash (#)
  // or have nothing but white-space preceeding the hash symbol
  rawLines.erase(remove_if(rawLines.begin(), rawLines.end(), [&expression, &what, &flags](const string& line)
  { return boost::regex_search(line.begin(), line.end(), what, expression, flags); }));
}

6
를 사용하여 명시 적으로 지정할 수 있습니다 ->. 예 :[&](double d) -> double { //...
Flexo

2
[&]...현재 가지고있는 것이 불필요하게 장황하기 때문에 필요한 변수 만 묵시적으로 캡처하는 것이 좋습니다.
Xeo

2
[&expression, &start, &end, &what, &flags]...(당신의) 대 [&]...(내). 이제 누가 더 장황한 지 말 해주세요. ;) [&]람다에 참조로 람다 본문 내부에서 사용하는 모든 것을 캡처하도록 지시합니다. 이를 "캡처 기본값"이라고합니다. 다른 하나는 [=]사본으로 캡처합니다.
Xeo

1
@Xeo, Effective Modern C ++, Item 31은 댕글 링 참조를 피하기 위해 명시 적으로 캡처 할 것을 권장합니다. 나 자신이 게으른 것에 대한 처벌로 몇 번이나 물린 적이 있습니다. 어, 간결합니다. :-)
Emile Cormier

2
그런데 C ++ 14에서 추론 된 반환형 람다에 대한 제약 조건이 줄어 듭니다. 본문에 두 개 이상의 문이있는 람다에 대한 반환 형식을 추론 할 수 있으며 각 return 문의식이 동일한 형식을 갖는 한 이제 여러 개의 반환 문이있는 추론 된 반환 형식을 가질 수 있습니다.
Anthony Hall

답변:


192

-> Type인수 목록 뒤에 를 사용하여 람다의 반환 유형을 명시 적으로 지정할 수 있습니다 .

[]() -> Type { }

그러나 람다에 하나의 문이 있고 해당 문이 return 문 (그리고 식을 반환 함) 인 경우 컴파일러는 반환 된 해당 표현식의 유형에서 반환 유형을 추론 할 수 있습니다. 람다에 여러 문이 있으므로 유형을 추론하지 않습니다.


4
컴파일러는 그렇게 할 수 있지만 표준은 그렇게하는 것을 금지합니다.
Johannes Schaub-litb

9
-1 : 이것은 컴파일러 버그가 아닙니다. 표준은 이것에 대해 매우 명확합니다. 섹션 5.1.2, 단락 4는 공제 방법과 공제 조건을 설명합니다.
Nicol Bolas 2012 년

2
최신 초안에서는 허용되지 않지만이 패치 gcc.gnu.org/ml/gcc-patches/2011-08/msg01901.html 에 대한 주석으로 진행되는 최종 사양에서 실제로 허용되는 것처럼 보입니다. . 누구든지 확인할 최종 사양이 있습니까?
Eelke

2
저는 람다 식을 광범위하게 사용했으며 한 번도 반환 유형을 명시 적으로 언급하지 않았습니다. 반환 유형의 추론 (적어도 VS2012 및 VS2013에서)은 람다 식에 둘 이상의 return 문이 있어도 완벽하게 작동합니다. 물론 다양한 return 문이 동일한 람다 식 내에서 일치해야합니다. 예 : "auto f = [] (int i) {if (i> 5) return true; return false;};" 문제없이 컴파일되며 "auto b = f (10);"를 호출하면 b는 bool 유형이며 물론 true입니다.
sprite

1
return nullptr;다른 포인터 유형이 반환되는 것처럼 유효하더라도 유형 추론에 렌치를 던질 수 있습니다.
Grault

16

람다의 반환 유형 (C ++ 11) 은 정확히 하나의 문이 있고 해당 문이 식을 반환하는 문인 경우 에만 추론 할 수 있습니다 return(예 : 이니셜 라이저 목록은식이 아님). 다중 문 람다가있는 경우 반환 유형은 무효로 간주됩니다.

따라서 다음을 수행해야합니다.

  remove_if(rawLines.begin(), rawLines.end(), [&expression, &start, &end, &what, &flags](const string& line) -> bool
  {
    start = line.begin();
    end = line.end();
    bool temp = boost::regex_search(start, end, what, expression, flags);
    return temp;
  })

그러나 실제로 두 번째 표현은 훨씬 더 읽기 쉽습니다.


좋은 예입니다. nitpick : );마지막에 함수 호출이 누락 되었습니까?
kevinarpe

6

여전히 반환 될 때 두 개 이상의 문을 가질 수 있습니다.

[]() -> your_type {return (
        your_statement,
        even_more_statement = just_add_comma,
        return_value);}

http://www.cplusplus.com/doc/tutorial/operators/#comma


4
쉼표는 반란을 일으키는 연산자입니다. 그것의 존재 또는 우선 순위 수준을 알지 못하는 사람들을 혼란스럽게합니다. imo는 유효한 용도가 없습니다. 더 많은 기능이나 그렇지 않으면 더 잘 구성된 코드로 항상 피할 수 있습니다.
jheriko

@jheriko는 동의합니다, 내 대답의 존재는 독립적 인 한 줄짜리 솔루션 XD를 정말로 원하는 사람들만을위한 것입니다 (여전히 한 줄입니다). 쉼표는 실제로 눈에 띄지 않으며 아무도 전체 주요 메서드를이 형식으로 입력하지 않습니다.
Valen

1
물론, 당신은 확실히 타당한 대답을하고 있습니다. 저는 단지 나쁜 습관을 장려하거나 증명하기 위해 어떤 일을하는 것을 좋아하지 않습니다. 일단 사람들이 쉼표가 운영자라는 것을 알게되면 그것을 남용하기 시작할 때까지 카운트 다운되고 더 잘 배울 때까지 더 긴 것입니다. :)
jheriko

@jheriko 한 번 회원 초기화 목록에서 흥미로운 용도로 사용하는 것을 보았지만 올바르게 기억한다면 그냥 엉망이 된 것입니다.
Justin Time-Monica 복원
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.