2017-10-21 1 views
2

현재 C++ 17 개 추가 기능을 탐색 중입니다. playing around withstd::variant 이후에 동일한 예제로 std::optional도 사용하고 싶습니다. 현재 컴파일이 다음 오류 때문에 실패보고 :C++ 17 : 람다에서 함수로 변환하지 못했습니다.

#pragma once 

#include <string> 
#include <utility> 
#include <functional> 
#include <optional> 

namespace dragon { 
    namespace html { 
     namespace parser { 
      template <typename ParserOutput, typename ParserInput = std::string> 
      using ParserResult = std::optional<std::pair<ParserOutput, ParserInput>>; 

      template<typename ParserOutput, typename ParserInput = std::string> 
      using Parser = std::function<ParserResult<ParserOutput, ParserInput>(ParserInput)>; 

      template <typename ParserOutput, typename ParserInput = std::string> 
      auto parse(Parser<ParserOutput, ParserInput> p, ParserInput i) -> ParserResult<ParserOutput, ParserInput>{ 
       return p(i); 
      } 

      // few parser combinators. 

      // thenP combinator: applies the first parser, if it succeeds apply the second to the rest of 
      // the input left over by the first parser. 
      // currently just fails and returns empty!! does not provide any debugging info/msg 
      // as to why the parsing failed. 
      template<typename FirstParser, typename SecondParser> 
      auto thenP(FirstParser f, SecondParser s) { 
       return [=](std::string input) -> decltype(parse(s, std::string())) { 
        auto fv = parse(f, input); 

        if (fv) { 
         auto fvv = *fv; 
         return parse(s, fvv.second); 
        } 
        else { 
         return {}; 
        } 
       }; 
      } 

      template<typename FirstParser, typename SecondParser> 
      auto choiceP(FirstParser f, SecondParser s) { 
       return [=](std::string input) { 
        auto fv = parse(f, input); 
        if (!fv) return parse(s, input); 
        return fv; 
       }; 
      } 

      auto charP(char match) -> Parser<char> { 
       return [=](std::string& input) -> ParserResult<char> { 
        if ((input.empty() == false) && (input[0] == match)) { 
         return std::make_pair(input[0], input.substr(1)); 
        } 
        return {}; 
       }; 
      } 
     } 
    } 
} 

나는 위의보고 있어요 :

error: no viable conversion from returned value of type 
     '(lambda at ./html_parser.hpp:53:9)' to function return type 'Parser<char>' (aka 
     'std::__1::function<std::__1::optional<std::__1::pair<char, std::__1::basic_string<char> > > 
     (std::__1::basic_string<char>)>') 
     return [=](std::string& input) -> ParserResult<char> { 
       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
/home/acid/tools/include/c++/v1/functional:1627:5: note: candidate constructor not viable: no known conversion 
     from '(lambda at ./html_parser.hpp:53:9)' to 'std::nullptr_t' (aka 'nullptr_t') for 1st argument 
    function(nullptr_t) _NOEXCEPT : __f_(0) {} 
    ^
/home/acid/tools/include/c++/v1/functional:1628:5: note: candidate constructor not viable: no known conversion 
     from '(lambda at ./html_parser.hpp:53:9)' to 'const 
     std::__1::function<std::__1::optional<std::__1::pair<char, std::__1::basic_string<char> > > 
     (std::__1::basic_string<char>)> &' for 1st argument 
    function(const function&); 
    ^
/home/acid/tools/include/c++/v1/functional:1629:5: note: candidate constructor not viable: no known conversion 
     from '(lambda at ./html_parser.hpp:53:9)' to 'std::__1::function<std::__1::optional<std::__1::pair<char, 
     std::__1::basic_string<char> > > (std::__1::basic_string<char>)> &&' for 1st argument 
    function(function&&) _NOEXCEPT; 
    ^
/home/acid/tools/include/c++/v1/functional:1631:5: note: candidate template ignored: requirement 
     '__callable<(lambda at ./html_parser.hpp:53:9)>::value' was not satisfied [with _Fp = 
     (lambda at ./html_parser.hpp:53:9)] 
    function(_Fp); 
    ^
1 error generated. 

는 DOM을 줄 수있는 HTML을 구문 분석하려면, 다음과 같이 몇 가지 파서 콤비를 선언 시작 아래 그림과 같이 간단한 사용을 컴파일 할 때 오류가 :

int main() 
{ 
    auto less = Parser::parser::charP('<'); 
    auto greater = Parser::parser::charP('>'); 

    auto lag = Parser::parser::thenP(less, greater); 
    auto log = Parser::parser::choiceP(less, greater); 

    auto lagv = lag("<>"); 
    auto logv = log("|>"); 

    return 0; 
} 

이 2017 년 (표준 = C++ - 최신) 비주얼 스튜디오와 잘 컴파일합니다. 그러나 Clang은 위의 오류를 제공합니다. 이 두 컴파일러 간의 불일치를 파악하려고합니다. 그리고 Clang과 함께이 문제를 해결하는 방법.

+3

앞으로는 [mcve]로 질문을 줄이십시오. 여기에는 무의미한 코드가 많아서 문제가 무엇인지 알기가 어렵습니다. – Barry

답변

5

이이 잘못 형성되어 동일한 이유로

auto charP(char match) -> Parser<char> { 
    return [=](std::string& input) -> ParserResult<char> { ... }; 
} 

이 잘못 형성되어 있음 : 오른쪽 람다는 int와 invocable 하지

std::function<void(int)> f = [](int&){}; 

이다

int&이므로 function<void(int)>을 생성 할 수 없습니다. MSVC에는 rvalue에서 비 const 왼쪽 값 참조를 구성 할 수있는 허용 모드가 있습니다. 아마 이것이 작동하는 이유 일 수 있습니다.

관련 문제