X3:非终端解析器上的链接器错误(未解析的外部符号"parse_rule")
X3: Linker Error (unresolved external symbol "parse_rule") on nonterminal parser
首先,我使用的是MSVC 2017(最新版本(。 这是我的非终端解析器代码:
玩家.hpp
namespace parse
{
namespace impl
{
namespace x3 = boost::spirit::x3;
struct _tag;
using player_type = x3::rule<_tag, PlayerIterator>;
using player_vector_type = x3::rule<_tag, std::vector<PlayerIterator>>;
BOOST_SPIRIT_DECLARE(player_type);
BOOST_SPIRIT_DECLARE(player_vector_type);
}; //impl
impl::player_type player();
impl::player_vector_type player_vector();
}; //parse
播放器.cpp
namespace parse
{
namespace impl
{
const player_type player = "player";
const player_vector_type player_vector = "player_vector";
auto player_find = [](auto &ctx)
{
auto &attr = x3::_attr(ctx);
if(attr.which() == 0)
return x3::_val(ctx) = PlayerManager::find(boost::get<int>(attr));
return x3::_val(ctx) = PlayerManager::find(boost::get<std::string>(attr));
};
auto player_vector_find = [](auto &ctx)
{
return x3::_val(ctx) = PlayerManager::vector_find(x3::_attr(ctx));
};
auto const player_def = (x3::int_ | (+x3::char_))[player_find];
auto const player_vector_def = (((+x3::char_)[player_vector_find]));
BOOST_SPIRIT_DEFINE(player);
BOOST_SPIRIT_DEFINE(player_vector);
BOOST_SPIRIT_INSTANTIATE(player_type, iterator_type, context_type);
BOOST_SPIRIT_INSTANTIATE(player_vector_type, iterator_type, context_type);
} //impl
parse::impl::player_type player() { return impl::player; }
parse::impl::player_vector_type player_vector() { return impl::player_vector; }
}//parse
我收到有关"引用未解析的外部符号"的链接器LNK2019错误:
Pastebin.com 错误链接 对他们有什么想法吗? 提前谢谢。
编辑: 这就是我在源文件中调用它的方式:
void test(std::string ¶ms)
{
std::tuple<PlayerIterator, std::vector<PlayerIterator>, std::string> tuple;
if (!x3::phrase_parse(params.begin(), params.end(), parse::player()>> parse::player_vector() >> (+x3::char_), x3::space,tuple))
{
std::cout << "Error: Parsing failed" << std::endl;
return;
}
std::cout << "Parsing succeded" << std::endl;
std::cout << "Found player, size of player vector: "<< std::get<1>(tuple).size() << ", also parsed string:" << std::get<2>(tuple);
return;
};
我愿意打赌 10 美元,你与实例上的上下文或迭代器类型不匹配。
例如,在您的test
函数中,参数是std::string&
的,因此params.begin()
将被std::string::iterator
。如果按如下方式配置了iterator_type
:
using iterator_type = std::string::const_iterator; // very sensible!
您将有未解析的外部,因为迭代器类型与实际需要的类型不匹配。
上下文也是如此。为了匹配您的调用,它需要完全是:
using context_type = x3::phrase_parse_context<x3::space_type>::type;
遗憾的是,您没有显示整个代码,因此您必须自己检查。
笔记
重复使用标签类型会导致灾难。我认为它行不通。规则标记是在分离编译单元的情况下调度实现函数的。修复它:
using player_type = x3::rule<struct player_tag, PlayerIterator>; using player_vector_type = x3::rule<struct player_vector_tag, std::vector<PlayerIterator>>;
复制规则似乎很浪费,请考虑通过引用返回:
impl::p layer_type const& player((; impl::p layer_vector_type const& player_vector((;
注意:这应该没问题,静态初始化顺序惨败
在变体上使用
which()
是一种反模式。您可以替换auto player_find = [](auto &ctx) { auto &attr = x3::_attr(ctx); if (attr.which() == 0) return x3::_val(ctx) = PlayerManager::find(boost::get<int>(attr)); return x3::_val(ctx) = PlayerManager::find(boost::get<std::string>(attr)); };
跟
auto find = [](auto const& key) { return PlayerManager::find(key); }; auto player_find = [](auto &ctx) { return x3::_val(ctx) = boost::apply_visitor(find, x3::_attr(ctx)); };
(+x3::char_)
始终匹配所有输入(+x3::graph)
仍然匹配所有输入,因为船长相反,你想要一个词法:
auto const name = x3::lexeme[+x3::graph]; auto const player_def = (x3::int_ | name) [player_find]; auto const player_vector_def = name[ player_vector_find];
我可以建议更简洁地编写
test
函数:void test(std::string const ¶ms) { auto comment_ = x3::lexeme[+x3::char_]; PlayerIterator player; PlayerIterators vec; std::string comment; auto tuple = std::tie(player, vec, comment); if (phrase_parse(params.cbegin(), params.cend(), parse::player() >> parse::player_vector() >> comment_, x3::space, tuple)) { std::cout << "Parsing succeded" << std::endl; std::cout << "Found player, size of player vector: " << vec.size() << "n"; std::cout << "Also parsed string: " << std::quoted(comment); } else { std::cout << "Error: Parsing failed" << std::endl; } }
完整演示
在魔杖盒上直播
东西.h
包含模型
PlayerManager
#pragma once #include <string> #include <vector> #include <iostream> struct PlayerIterator { }; using PlayerIterators = std::vector<PlayerIterator>; struct PlayerManager { static PlayerIterator find(std::string const&) { std::cout << __PRETTY_FUNCTION__ << "n"; return {}; } static PlayerIterator find(int) { std::cout << __PRETTY_FUNCTION__ << "n"; return {}; } static PlayerIterators vector_find(std::string const&) { std::cout << __PRETTY_FUNCTION__ << "n"; return {}; } };
测试.h
#pragma once #include <boost/spirit/home/x3.hpp> #include <boost/fusion/adapted.hpp> #include "stuff.h" namespace x3 = boost::spirit::x3; namespace parse { namespace impl { using player_type = x3::rule<struct player_tag, PlayerIterator>; using player_vector_type = x3::rule<struct player_vector_tag, PlayerIterators>; BOOST_SPIRIT_DECLARE(player_type) BOOST_SPIRIT_DECLARE(player_vector_type) } //impl impl::player_type const& player(); impl::player_vector_type const& player_vector(); } //parse
测试.cpp
#include "stuff.h" #include "test.h" using iterator_type = std::string::const_iterator; using context_type = x3::phrase_parse_context<x3::space_type>::type; namespace parse { namespace impl { const player_type player = "player"; const player_vector_type player_vector = "player_vector"; auto find = [](auto const& key) { return PlayerManager::find(key); } ; auto player_find = [](auto &ctx) { return x3::_val(ctx) = boost::apply_visitor(find, x3::_attr(ctx)); } ; auto player_vector_find = [](auto &ctx) { return x3::_val(ctx) = PlayerManager::vector_find(x3::_attr(ctx)); } ; auto const name = x3::lexeme[+x3::graph]; auto const player_def = (x3::int_ | name) [player_find]; auto const player_vector_def = name[ player_vector_find]; BOOST_SPIRIT_DEFINE(player) BOOST_SPIRIT_DEFINE(player_vector) BOOST_SPIRIT_INSTANTIATE(player_type, iterator_type, context_type) BOOST_SPIRIT_INSTANTIATE(player_vector_type, iterator_type, context_type) } // namespace impl parse::impl::player_type const& player() { return impl::player; } parse::impl::player_vector_type const& player_vector() { return impl::player_vector; } } // namespace parse
主.cpp
#include "stuff.h" #include "test.h" #include <iostream> #include <iomanip> void test(std::string const ¶ms) { auto comment_ = x3::lexeme[+x3::char_]; PlayerIterator player; PlayerIterators vec; std::string comment; auto tuple = std::tie(player, vec, comment); if (phrase_parse(params.cbegin(), params.cend(), parse::player() >> parse::player_vector() >> comment_, x3::space, tuple)) { std::cout << "Parsing succeded" << std::endl; std::cout << "Found player, size of player vector: " << vec.size() << "n"; std::cout << "Also parsed string: " << std::quoted(comment); } else { std::cout << "Error: Parsing failed" << std::endl; } } int main() { test("42 someword # bogus trailing comment"); }
指纹:
static PlayerIterator PlayerManager::find(int)
static PlayerIterators PlayerManager::vector_find(const std::string &)
Parsing succeded
Found player, size of player vector: 0
Also parsed string: "# bogus trailing comment"
相关文章:
- C++:Application.cpp中抛出了未解析的外部符号(解决方案在问题的末尾,供未来的读者参考)
- 未解析的外部符号_MsiLocateComponentW@12.
- 在C++中使用 gRPC 时未解析的外部符号
- LibPrivoxy: 未解析的外部符号 __declspec(dllimport) int __stdcall Sta
- 尝试从 XamlApplication 编译 C++/WinRT 空白应用程序时,我收到未解析的外部符号 winrt_make_*
- 我收到错误LNK2001:未解析的外部符号(C++代码)
- 可视抽象类 c++(错误 LNK 2001:未解析的外部符号)
- 如何摆脱C++中未解析的外部符号"private: static char"错误?
- 当 lib 已添加到其他依赖项时,如何在 VS 中调试未解析的外部符号错误
- 仅在少数方法(静态或共享库)中解析的外部符号
- 未解析的外部符号"__declspec(dllimport)与 Spdlog c++ 库
- 函数 _main (OPENGL C++) 中引用的未解析的外部符号 ________
- 错误LNK2019未解析的外部符号"public: __thiscall SLinkList<char>::SLinkList<char>(void)"
- 使用静态 constexpr 成员的未解析外部符号
- 引入参数化构造函数后显示 LNK 2019 未解析外部符号的代码错误
- Dlib LNK2001未解析的外部符号USER_ERROR__consistent_build_configurati
- 矛盾的未解决的外部符号+未使用的库与VS2017和FFMPEG 4
- 链接器错误:切换到unicode生成给出:未解析的外部符号WinMain
- 错误 LNK2019:未解析的外部符号"外部"C"此错误是什么?
- 错误 : LNK2019: 未解析的外部符号"外部 "C"