Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/137.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 检测语义动作中的参数类型_C++_Compiler Errors_Boost Spirit - Fatal编程技术网

C++ 检测语义动作中的参数类型

C++ 检测语义动作中的参数类型,c++,compiler-errors,boost-spirit,C++,Compiler Errors,Boost Spirit,一般情况:我不明白为什么我的Spirit语法/语义操作没有编译 有时,编译器会抱怨赋值或类型不兼容,我不知道哪里出了问题。问题主要出现在两个方面: 预测规则/表达式的合成属性类型 因此,预测哪些类型的属性可以合法地定义为规则的公开属性(依赖于内置转换、融合适配器或Spirit定制点) 匹配语义操作的参数类型,以便 编译器将能够编译函数调用 调用不会调用进程中不必要的隐式转换 编译器错误不是很容易处理的,或者文档是错误的,或者我误解了它 有没有一种方法可以准确地找出什么样的精神传递到我

一般情况:我不明白为什么我的Spirit语法/语义操作没有编译

有时,编译器会抱怨赋值或类型不兼容,我不知道哪里出了问题。问题主要出现在两个方面:

  • 预测规则/表达式的合成属性类型
    • 因此,预测哪些类型的属性可以合法地定义为规则的公开属性(依赖于内置转换、融合适配器或Spirit定制点)
  • 匹配语义操作的参数类型,以便
    • 编译器将能够编译函数调用
    • 调用不会调用进程中不必要的隐式转换
编译器错误不是很容易处理的,或者文档是错误的,或者我误解了它

有没有一种方法可以准确地找出什么样的精神传递到我的语义动作中?

示例代码:
structmybase{inta,b;};
结构myderived:mybase{int c,d;};
BOOST_FUSION_ADAPT_STRUCT(mybase,(int,a)(int,b));
BOOST_FUSION_ADAPT_STRUCT(myderived,(int,a)(int,b)(int,c)(int,d));
自动基函数expr=int\u>>int\u;//避免指定给struct属性
规则库\=int \>>int;
规则派生\=base \>>int \>>int \;
我的衍生数据;
bool ok=短语解析(f,l,派生的,空间,数据);
这段代码无法编译,有大量无法穿透的错误


(松散地改编自列表上的帖子)

为了清晰起见-这里的错误是
base\u>>int\u>>int\u
被用作创建
myderived
的规则的表达式,并且由于
base\u
被固定为type
mybase
,我们必须从一个
mybase
和两个
int
s创建一个
myderrive
,但是没有什么可以告诉Spirit怎么做

您可以让boost打印出boost通过解析
base\u>>int\u>>int\u>/code>创建的值的类型,方法是定义一个接受任何参数的函子,并告诉您它们是什么(下面的代码改编自他在SO chat上发布的一些代码):


第一行,
boost::fusion::vector3
,至少告诉您boost正在尝试从类型为
mybase
int
int
的3个对象创建返回类型,我可以解决这个特定情况下的问题(事实上),但实际上,这种 “神秘”的错误会随着精神振奋而更频繁地出现,这将是一件好事 来处理一般类型的问题

您的第一个资源应该是优秀的spirit文档,它 详细说明给定解析器的合成属性是什么 原语、运算符或指令。看见 对

在某些情况下,我已经开始将注意力从“试图窥探真相”转移到 编译器错误列表“to”中的信息主动查询 输入“它通过”。我为此使用的技术是多态可调用类型 (参见Spirit/Fusion文档)

下面是一个使用特定于GCC的API漂亮地[sic]打印它检测到的类型的应用程序:

函子
属性是什么
输出:

what_is_the_attr: boost::optional<boost::fusion::vector2<int, std::vector<int, std::allocator<int> > > >
what_is_the_attr: boost::iterator_range<char const*>
对上述测试用例的重复显示,Spirit实际上试图调用 如果可能,语义操作包含三个参数(如下所示):

将打印

what_is_the_attr: boost::fusion::vector3<mybase, int, int>
what_is_the_attr: boost::fusion::vector4<int, int, int, int>
什么是属性:boost::fusion::vector3 什么是属性:boost::fusion::vector4
这是你的问题。我们在中讨论了基于此诊断的一些变通方法(请参见此处的其他答案)。但这篇文章应该有助于回答一般的案例问题

完整代码清单 以集成形式,使用gcc 4.6.1--std=c++0x和boost 1_48编译:

#include <cxxabi.h>
#include <iostream>
#include <iterator>
#include <stdlib.h>
#include <string>
#include <vector>

template <typename T> std::string nameofType(const T& v)
{
    int     status;
    char   *realname = abi::__cxa_demangle(typeid(v).name(), 0, 0, &status);
    std::string name(realname? realname : "????");
    free(realname);

    return name;
}

struct what_is_the_attr {
    template <typename> struct result { typedef bool type; };

    template <typename T> bool operator()(T& attr) const {
        std::cerr << "what_is_the_attr: " << nameofType(attr) << std::endl;
        return true;
    }
};

struct what_are_the_arguments {
    template <typename...> struct result { typedef bool type; };

    template <typename... T> bool operator()(const T&... attr) const {
        std::vector<std::string> names { nameofType(attr)... };
        std::cerr << "what_are_the_arguments:\n\t";
        std::copy(names.begin(), names.end(), std::ostream_iterator<std::string>(std::cerr, "\n\t"));
        std::cerr << '\n';
        return true;
    }
};

#include <boost/fusion/adapted.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>

struct mybase             { int a,b; };
struct myderived : mybase { int c,d; };

BOOST_FUSION_ADAPT_STRUCT(mybase,    (int,a)(int,b));
BOOST_FUSION_ADAPT_STRUCT(myderived, (int,a)(int,b)(int,c)(int,d));

template <typename ExpWSA>
void test(const ExpWSA& exp)
{
    using namespace boost::spirit::qi;

    const char input[] = "1 2 3 4";
    auto f(std::begin(input)), l(std::end(input)-1);

    bool dummy = phrase_parse(f, l, exp, space);
}

int main()
{
    using namespace boost::spirit::qi;

    // Diagnostics for the OP case
    auto base_expr = int_ >> int_;                                   // avoids assigning to struct attribute
    rule<const char*, mybase(), space_type> base_       = base_expr;

    // Derived rule, different formulations
    test((base_     >> int_ >> int_) [ what_is_the_attr() ] );
    test((base_expr >> int_ >> int_) [ what_is_the_attr() ] );

    // Applied to attribute types
    test(raw [ -(int_ >> *int_) ]  [ what_is_the_attr() ] );
    test(-(int_ >> *int_)          [ what_is_the_attr() ] );

    // applied to semantic actions - contrived example
    namespace phx = boost::phoenix;
    test(-(-double_ >> *int_) [ phx::bind(what_are_the_arguments(), _1, _2, _0, phx::ref(std::cout), 42) ]);

    return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
模板std::字符串类型名称(常量T&v)
{
智力状态;
char*realname=abi::\uuucxa\udemangle(typeid(v).name()、0、0和状态);
std::字符串名(realname?realname:“??”);
免费(域名);
返回名称;
}
结构什么是属性{
模板结构结果{typedef bool type;};
模板布尔运算符()(T&attr)常量{
std::cerr>int(什么是属性());
测试((base_expr>>int_>>int)[什么是属性()];
//应用于属性类型
测试(原始[-(int_>>*int)][属性是什么];
测试(-(int_>>*int)[什么是属性()];
//应用于语义动作-人为示例
名称空间phx=boost::phoenix;
测试(-double_>>*int_u)[phx::bind(什么是参数(),1,2,0,phx::ref(std::cout),42)];
返回0;
}

+1用于改进typename打印的TypeTrait向导。酷!+1正是我作为一个新手每天都在努力解决的问题。。。
$ g++ 9404189.cpp -std=c++0x
$ ./a.out |c++filt -t
what_is_the_attr(
    boost::fusion::vector3<mybase, int, int> &,
    boost::spirit::context<boost::fusion::cons<boost::spirit::unused_type&, boost::fusion::nil>, boost::fusion::vector0<void> > &,
    bool &)
#include <cxxabi.h>
#include <stdlib.h>
#include <string>
#include <iostream>

template <typename T> std::string nameofType(const T& v) {
    int     status;
    char   *realname = abi::__cxa_demangle(typeid(v).name(), 0, 0, &status);
    std::string name(realname? realname : "????");
    free(realname);
    return name;
}

struct what_is_the_attr {
    template <typename> struct result { typedef bool type; };

    template <typename T> bool operator()(T& attr) const {
        std::cerr << "what_is_the_attr: " << nameofType(attr) << std::endl;
        return true;
    }
};
template <typename Exp>
    void detect_attr_type(const Exp& exp)
{
    using namespace boost::spirit::qi;

    const char input[] = "1 2 3 4";
    auto f(std::begin(input)), l(std::end(input)-1);

    bool dummy = phrase_parse(
            f, l, 
            exp [ what_is_the_attr() ],
            space);
}
int main()
{
    detect_attr_type(       -(int_ >> *int_)    );
    detect_attr_type( raw [ -(int_ >> *int_) ] );
}
what_is_the_attr: boost::optional<boost::fusion::vector2<int, std::vector<int, std::allocator<int> > > >
what_is_the_attr: boost::iterator_range<char const*>
struct what_are_the_arguments {
    template <typename...> struct result { typedef bool type; };

    template <typename... T> bool operator()(const T&... attr) const {
        std::vector<std::string> names { nameofType(attr)... };
        std::cerr << "what_are_the_arguments:\n\t";
        std::copy(names.begin(), names.end(), std::ostream_iterator<std::string>(std::cerr, "\n\t"));
        std::cerr << '\n';
        return true;
    }
};
what_are_the_arguments:
    boost::optional<boost::fusion::vector2<int, std::vector<int, std::allocator<int> > > >
    boost::spirit::unused_type
    bool

what_are_the_arguments:
    boost::iterator_range<char const*>
    boost::spirit::unused_type
    bool
template <typename ExpWSA> void test(const ExpWSA& exp)
{
    const char input[] = "1 2 3 4";
    auto f(std::begin(input)), l(std::end(input)-1);

    qi::phrase_parse(f, l, exp, qi::space);
}

int main()
{
    test(-(-double_ >> *int_) [ phx::bind(what_are_the_arguments(), _1, _2, _0, phx::ref(std::cout), 42) ]);
}
what_are_the_arguments:
    boost::optional<double>
    std::vector<int, std::allocator<int> >
    boost::fusion::vector2<boost::optional<double>, std::vector<int, std::allocator<int> > >
    std::ostream
    int
auto base_expr = int_ >> int_; // avoids assigning to struct attribute

rule<const char*, mybase(), space_type> base_       = base_expr;

test(base_     >> int_ >> int_ [ what_is_the_attr() ] );
test(base_expr >> int_ >> int_ [ what_is_the_attr() ] );
what_is_the_attr: boost::fusion::vector3<mybase, int, int>
what_is_the_attr: boost::fusion::vector4<int, int, int, int>
#include <cxxabi.h>
#include <iostream>
#include <iterator>
#include <stdlib.h>
#include <string>
#include <vector>

template <typename T> std::string nameofType(const T& v)
{
    int     status;
    char   *realname = abi::__cxa_demangle(typeid(v).name(), 0, 0, &status);
    std::string name(realname? realname : "????");
    free(realname);

    return name;
}

struct what_is_the_attr {
    template <typename> struct result { typedef bool type; };

    template <typename T> bool operator()(T& attr) const {
        std::cerr << "what_is_the_attr: " << nameofType(attr) << std::endl;
        return true;
    }
};

struct what_are_the_arguments {
    template <typename...> struct result { typedef bool type; };

    template <typename... T> bool operator()(const T&... attr) const {
        std::vector<std::string> names { nameofType(attr)... };
        std::cerr << "what_are_the_arguments:\n\t";
        std::copy(names.begin(), names.end(), std::ostream_iterator<std::string>(std::cerr, "\n\t"));
        std::cerr << '\n';
        return true;
    }
};

#include <boost/fusion/adapted.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>

struct mybase             { int a,b; };
struct myderived : mybase { int c,d; };

BOOST_FUSION_ADAPT_STRUCT(mybase,    (int,a)(int,b));
BOOST_FUSION_ADAPT_STRUCT(myderived, (int,a)(int,b)(int,c)(int,d));

template <typename ExpWSA>
void test(const ExpWSA& exp)
{
    using namespace boost::spirit::qi;

    const char input[] = "1 2 3 4";
    auto f(std::begin(input)), l(std::end(input)-1);

    bool dummy = phrase_parse(f, l, exp, space);
}

int main()
{
    using namespace boost::spirit::qi;

    // Diagnostics for the OP case
    auto base_expr = int_ >> int_;                                   // avoids assigning to struct attribute
    rule<const char*, mybase(), space_type> base_       = base_expr;

    // Derived rule, different formulations
    test((base_     >> int_ >> int_) [ what_is_the_attr() ] );
    test((base_expr >> int_ >> int_) [ what_is_the_attr() ] );

    // Applied to attribute types
    test(raw [ -(int_ >> *int_) ]  [ what_is_the_attr() ] );
    test(-(int_ >> *int_)          [ what_is_the_attr() ] );

    // applied to semantic actions - contrived example
    namespace phx = boost::phoenix;
    test(-(-double_ >> *int_) [ phx::bind(what_are_the_arguments(), _1, _2, _0, phx::ref(std::cout), 42) ]);

    return 0;
}