Oleg Bogdanov Oleg Bogdanov - 1 year ago 96
C++ Question

clang vs gcc in abstract class handling in compile time

One of these issues of nlohmann/json opensource library drew my attention.

I have a minimal reproduction of the case that does not compile under few version of desktop gcc (4.8, 4.9, also tried 5+) but compiles well with mac clang and Android ndk's gcc 4.9

#include <limits>

struct base {
virtual void foo() = 0;

int main() {

GCC is trying to instantiate
with base class instead of derived:

/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(); }

I'm not quite sure if this is a known compiler bug (in case of failure) or feature/relaxed rule (in case of success)

I've tried to work it around with
but it does not help, looks like 'short-circuit' evaluation is not happening in enable_if and error stays the same

My question mainly is not how to fix this for gcc but weather this is compiler bug or code bug

Edit: added "more minimal" example without any standard library dependency:

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

struct abstract
virtual ~abstract() = 0;

int main()
(void) foo<abstract>::value;

Compiles on clang 3.9.0, but gcc 7 snapshot emits an error for the invalid return type of

Edit2: I'm a bit surprised that my initial question was edited without my consent, was not aware that SO allows that :) Thanks for help though I think it brought a bit of confusion and wrong answers, mainly because text and code were not connected anymore

Answer Source

No, it is not a bug. It is just a bad test.


The only difference between GCC and clang in this case is the way they process template class functions:

  • GCC: All of them in once.
  • clang: Only the one that has been used.

In our first example, the function min() doesn't get called, and therefore, clang doesn't has a problem with it. GCC, parses all the functions and find out that min() is invalid.

In the second example, the same happens: bar() doesn't get called by anyone and therefore clang is OK about it being ill-formed. But again, GCC, have a problem with it, although hasn't been used anywhere in the program.

A good test

Saying that something is bad is not enough, let's fix it: this example would fail with both GCC and clang with almost the same error (invalid abstract return type ‘base’ or allocating an object of abstract class type 'base').

#include <limits>

struct base {
    virtual void foo() = 0;

int main() {
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download