【问题标题】:Error: "incomplete type is not allowed" while porting project错误:移植项目时“不允许不完整的类型”
【发布时间】:2012-05-06 10:39:44
【问题描述】:

我正在将http://www.drdobbs.com/embedded-systems/225700666 移植到Keil MDK 用于ARM 微处理器。该框架可以在我的桌面上使用gcc 编译并正常工作,但使用Keil 编译器会给我一个错误:

logging/singleton.h(65): error: #70: incomplete type is not allowed

以下代码显示了 singleton 的实现,我收到此错误。这个错误是从哪里来的?

namespace logging {

  namespace detail {

      template <typename T>
      class singleton
      {
        private:
          struct obj
          {
            obj() { singleton<T>::instance(); }
            inline void empty() const { }
          };
          static obj __obj;

          singleton();

        public:
          typedef T obj_type;

          static obj_type & instance()
          {
            static obj_type obj;  // <-- Here I get this error

            __obj.empty();

            return obj;
          }
      };
      template <typename T>
      typename singleton<T>::obj
      singleton<T>::__obj;

  } /* detail */
} /* logging */

编辑: singleton在这里被实例化

template <typename log_t, typename T>
struct Obj {
    static return_type& obj () {
        typedef singleton<return_type> log_output;
        return log_output::instance();
    }
}; 

return_type 是一个 typedef:

typedef R return_type;

这是父模板的参数:

template<typename Level = ::logging::Void, typename R = loggingReturnType>
    class Logger {
       ...
    };

loggingReturnType 在类定义上方前向声明:

struct loggingReturnType;

编辑 2: 这个loggingReturnType是通过跟随makro生成的。

#define LOGGING_DEFINE_OUTPUT(BASE)                                           \
namespace logging {                                                           \
    struct loggingReturnType : public BASE {                                  \
            /*! \brief The provided typedef is used for compile time          \
             *         selection of different implementation of the           \
             *         %logging framework. Thus, it is necessary              \
             *         that any output type supports this type                \
             *         definition, why it is defined here.                    \
             */                                                               \
            typedef BASE    output_base_type;                                 \
        };                                                                    \
}

这个 makro 在配置头中被调用。

编辑 3: 她是预处理器输出的链接:http://www.pasteall.org/31617/cpp。这个文件使用g++ 编译得很好。 loggingReturnType 的定义是 main 之前的最后一个 - 所以单例不是确切的类型,但它仍然有效。我还查看了Keil 编译器的预处理器输出,几乎相同。

那么这里出了什么问题?

【问题讨论】:

  • 你传递给单例模板的类型是什么?看起来类型 T 不完整(抽象)。
  • incomplete 类型与 abstract 类型不同。
  • 我已经添加了那个单例的实例化。

标签: c++ templates singleton incomplete-type


【解决方案1】:

根据您在此处输入的信息,错误消息非常合理。该代码试图在堆栈上创建一个对象的实例。该对象的类型只是前向声明的,但当时编译器没有可用的定义。

在必须创建此类型的实例之前,您需要使编译器可以使用此类型的定义。

【讨论】:

  • 我已经为这个类型的定义添加了一些代码。是不是编译顺序有问题?
  • @Razer 在使用这种类型之前,调用宏的配置头是否包含在翻译单元中(直接或间接)?
  • 文件Logger.h 保存了单例的实例和makro 的定义。 makro 在logging.h 中被调用——但这是在包含Logger.h 之后完成的。我现在很困惑 - 'Logger.h' 如何实例化这样的单例? @selalerer 是的-如果我在该文件中产生错误,编译器会大喊。不幸的是,我不知道如何使用 Keil 的编译器输出翻译单元
  • @Razer 尝试更改包含的顺序(在 Logger.h 之前包括 logging.h)。
  • 嗯,奇怪的是我用gcc完美编译。主文件仅包含logging.h,并且如前所述直接包含Logger.h
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-03
  • 1970-01-01
  • 2011-08-12
  • 2017-03-05
相关资源
最近更新 更多