Cap'n Proto сгенерированный исходный код C++ не компилируется

У меня проблемы с этим фрагментом кода capnp:

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

Я создал и скомпилировал исходный код на С ++ так:

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.

1 ответ

Решение

Остальная часть этого ответа устарела. Эта проблема больше не должна появляться с версии 0.6.0 capnp.


Как только я закончил писать свой вопрос, я хотел проверить это и с помощью clang, и это фактически заставило меня найти ошибку. Я все еще решил опубликовать вопрос, так как я уже закончил писать. Проблема в том, что KJ_IREQUIRE является макросом, и поскольку макросы - вещь, которую обрабатывает препроцессор, их семантика очень уродлива. Запятая в аргументах шаблона для Result интерпретируется как разделитель аргументов для макроса, что приводит к этому действительно бесполезному сообщению об ошибке в g++, но гораздо приятнее в clang.

Чтобы обойти это, вы можете добавить еще один набор скобок вокруг аргументов KJ_IREQUIRE, Я надеюсь, что эта часть документации может кому-то помочь!

Другие вопросы по тегам