2017-10-21 16 views
2

現在、私はC++ 17の追加を検討中です。 playing around withstd::variantの後に同じ例でstd::optionalも使用したかったです。現在、コンパイルが次のエラーのため失敗したことを見て:C++ 17:ラムダからstd ::関数への変換の失敗

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を解析するには、次のようにいくつかのパーサコンビネータを宣言して開始しました:

#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 {}; 
       }; 
      } 
     } 
    } 
} 

私は上記を見ています

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; 
} 

これは、Visual Studio 2017( - 最新のstd = C++)と罰金コンパイル:以下に示すように簡単な使用をコンパイルしようと、エラー、。しかし、Clangは上記のエラーを出します。これらの2つのコンパイラ間の不一致を理解しようとしています。そしてこの問題をClangと解決する方法。

+3

今後、[mcve]に質問を減らしてみてください。ここに無関係なコードがたくさんあるので、問題の内容を確認するのが難しくなります。 – Barry

答えて

5

これは悪い形成されている:これは悪い形成されているのと同じ理由で

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

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

右側のラムダがintない呼び出し可能で、のみint&ですので、function<void(int)>を作成することはできません。 MSVCには、rvalueから非const左辺参照を構築することができるいくつかの許容モードがあります。おそらくそれがうまく機能しています。

関連する問題