Cap'n 原型生成的 c++ 源代码无法编译

Cap'n proto generated c++ source doesn't compile

本文关键字:c++ 源代码 编译 原型 Cap      更新时间:2023-10-16

我对这段capnp代码有问题:

struct Result(Success, Error) {
    union {
        success @0 :Success;
        error   @1 :Error;
    }
}

我创建并编译了c++源代码,如下所示:

capnp compile -oc++ test.capnp
g++ -o test.capnp.o test.capnp.c++ `pkg-config --cflags capnp` -std=c++11

和我得到这个相同的错误(和相同的错误,而不是成功)在多个位置在生成的头文件:

error: type/value mismatch at argument 2 in template parameter list for ‘template<class Success, class Error> struct Result’
   KJ_IREQUIRE(which() == Result<Success, Error>::SUCCESS,
   ^
error:   expected a type, got ‘true’
error: expected primary-expression before ‘>’ token
   KJ_IREQUIRE(which() == Result<Success, Error>::SUCCESS,
                                               ^
error: ‘::SUCCESS’ has not been declared
   KJ_IREQUIRE(which() == Result<Success, Error>::SUCCESS,
                                                ^

这是g++抱怨的一个定义:

template <typename Success, typename Error>
inline  ::capnp::ReaderFor<Success> Result<Success, Error>::Reader::getSuccess() const {
  KJ_IREQUIRE(which() == Result<Success, Error>::SUCCESS,
              "Must check which() before get()ing a union member.");
  return ::capnp::_::PointerHelpers<Success>::get(
      _reader.getPointerField(0 * ::capnp::POINTERS));
}

我真的不明白为什么g++不接受这个…

我使用capnproto 0.5.3(第一次遇到这个问题是在0.5.2,然后更新,看看是否有帮助)和g++ 4.9.2。

这个答案的其余部分已经过时了。

从capnp 0.6.0版本开始,这个问题应该不再出现了。

就在我写完问题的时候,我也想用clang测试一下,它实际上让我找到了错误。我还是选择把这个问题贴出来,因为我已经写完了。问题是KJ_IREQUIRE是一个宏,而宏是预处理器处理的东西,它们的语义非常丑陋。Result模板参数中的逗号被解释为宏的参数分隔符,这在g++中导致了这个非常无用的错误消息,但在clang中却是一个好得多的错误消息。

要解决这个问题,可以在KJ_IREQUIRE的参数周围添加另一组括号。我希望这一点文档可以帮助别人!