clang vs gcc在编译时的抽象类处理中

Ole*_*nov 6 c++ gcc abstract-class clang

nlohmann/json开源库的其中一个问题引起了我的注意.

我的情况下的最小再现那无法编译桌面GCC(4.8,4.9,还试图5+)的几个版本下却与Mac铛和Android NDK的GCC编译以及4.9

#include <limits>

struct base {
    virtual void foo() = 0;
};

int main() {
    (void)numeric_limits<base>::is_signed;
}
Run Code Online (Sandbox Code Playgroud)

GCC试图std::numeric_limits用基类实例化而不是派生:

/usr/include/c++/4.8/limits: In instantiation of 'struct std::numeric_limits<base>': main.cpp:11:94:   required from here
/usr/include/c++/4.8/limits:309:7: error: cannot allocate an object of abstract type 'base'
min() _GLIBCXX_USE_NOEXCEPT { return _Tp(); }
Run Code Online (Sandbox Code Playgroud)

我不太确定这是一个已知的编译器错误(如果失败)或功能/放宽规则(如果成功)

我试图解决它,std::is_abstract但它没有帮助,看起来像'短路'评估没有发生在enable_if和错误保持不变

我的问题主要不是如何为gcc修复此问题,但天气这是编译器错误或代码错误


编辑:添加"更多最小"示例,没有任何标准库依赖:

template <typename T>
struct foo
{
  static T bar();
  static constexpr bool value = true;
};

struct abstract
{
  virtual ~abstract() = 0;
};

int main()
{
  (void) foo<abstract>::value;
}
Run Code Online (Sandbox Code Playgroud)

在clang 3.9.0上编译,但gcc 7快照为无效的返回类型发出错误foo<abstract>::bar.


编辑2:我有点惊讶我的初始问题是在未经我同意的情况下编辑的,不知道SO允许:)感谢帮助虽然我认为它带来了一些混乱和错误的答案,主要是因为文本和代码不是连接了

Shm*_* H. 1

,这不是一个错误。这只是一个糟糕的测试。

\n\n

描述

\n\n

GCC在这种情况下,和之间的唯一区别clang是它们处理模板类函数的方式:

\n\n
    \n
  • GCC: 全部一次。
  • \n
  • clang: 仅限使用过的那一款。
  • \n
\n\n

在我们的第一个示例中,该函数min()没有被调用,因此clang没有问题。GCC,解析所有函数并发现min()无效的。

\n\n

在第二个示例中,发生了同样的情况:bar()没有被任何人调用,因此clang它的格式不正确是可以接受的。但话又说回来,GCC尽管没有在程序中的任何地方使用过,但还是有问题。

\n\n

一个好的测试

\n\n

仅仅说某件事不好是不够的,让我们修复它:这个例子将因两者而失败GCC,并且clang出现几乎相同的错误(invalid abstract return type \xe2\x80\x98base\xe2\x80\x99allocating an object of abstract class type 'base')而失败。

\n\n
#include <limits>\n\nstruct base {\n    virtual void foo() = 0;\n};\n\nint main() {\n    (void)std::numeric_limits<base>::min();\n}\n
Run Code Online (Sandbox Code Playgroud)\n