Reputation: 1732
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() {
(void)numeric_limits<base>::is_signed;
}
GCC is trying to instantiate std::numeric_limits
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 std::is_abstract
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 foo<abstract>::bar
.
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
Upvotes: 6
Views: 531
Reputation: 2546
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.
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() {
(void)std::numeric_limits<base>::min();
}
Upvotes: 1