c++17:lambda 到 std::function 转换失败
c++17 : lambda to std::function conversion failure
我目前正在研究 c++17 的新增功能。在 std::variant
之后,也想用 std::optional
,同一个例子。目前看到由于以下错误导致编译失败:
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.
要解析 HTML 以得到 DOM,首先声明一些解析器组合器,如下所示:
#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++-latest) 编译良好。但是 Clang 给出了上述错误。试图找出这两个编译器之间的差异。以及如何使用 Clang 解决此问题。
这是错误的:
auto charP(char match) -> Parser<char> {
return [=](std::string& input) -> ParserResult<char> { ... };
}
与格式错误的原因相同:
std::function<void(int)> f = [](int& ){};
右边的lambda 不能用int
调用,只能用int&
调用,所以你不能构造function<void(int)>
] 从里面出来。 MSVC 有一些宽容模式,它允许从右值构造一个非常量左值引用,这可能就是它起作用的原因。
我目前正在研究 c++17 的新增功能。在 std::variant
之后,也想用 std::optional
,同一个例子。目前看到由于以下错误导致编译失败:
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.
要解析 HTML 以得到 DOM,首先声明一些解析器组合器,如下所示:
#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++-latest) 编译良好。但是 Clang 给出了上述错误。试图找出这两个编译器之间的差异。以及如何使用 Clang 解决此问题。
这是错误的:
auto charP(char match) -> Parser<char> {
return [=](std::string& input) -> ParserResult<char> { ... };
}
与格式错误的原因相同:
std::function<void(int)> f = [](int& ){};
右边的lambda 不能用int
调用,只能用int&
调用,所以你不能构造function<void(int)>
] 从里面出来。 MSVC 有一些宽容模式,它允许从右值构造一个非常量左值引用,这可能就是它起作用的原因。