Reputation: 38228
The following code:
#include <cstdint>
#include <type_traits>
enum class Enum : std::uint64_t {
zero,
};
static_assert(std::is_same<std::make_unsigned<Enum>::type, std::uint64_t>::value, "");
fails to compile on OS X with clang:
$ clang++ -std=c++11 -c t.cpp
t.cpp:8:1: error: static_assert failed ""
static_assert(std::is_same<std::make_unsigned<Enum>::type, std::uint64_t>::value, "");
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated
However, this same file works okay with clang 3.8/3.7.1/3.7/3.6/3.5.1/3.5/3.4.1/3.3 on gcc.godbolt.org.
On my system, clang is just the normal version from Xcode 7.3.1:
$ clang++ --version
Apple LLVM version 7.3.0 (clang-703.0.31)
Target: x86_64-apple-darwin15.4.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
What gives? This clearly seems to be a bug in clang on my system, but it's not clear to me why this would fail with clang from Xcode but not any of the other versions of clang. Is Xcode's clang distribution significantly different?
Upvotes: 3
Views: 1048
Reputation: 137425
This is not a bug; the behavior is mandated by the standard. [meta.trans.sign] says for the enumeration case
type
shall name the unsigned integer type with smallest rank ([conv.rank]) for whichsizeof(T) == sizeof(type)
, with the same cv-qualifiers asT
.
In platforms where sizeof(unsigned long long) == sizeof (unsigned long)
, std::uint64_t
may be defined as either, but std::make_unsigned<Enum>::type
must name unsigned long
.
Upvotes: 5