1
votes

I just stumbled into the following user-defined literal:

#include <cstdint>

constexpr auto operator""_G(uint64_t v) { return v * 1'000'000'000ULL; }

However, this does not compile with GNU 7.3.0 and -std=c++14. I get an "has invalid argument list" error.

According to https://en.cppreference.com/w/cpp/language/user_literal, the only allowed unsigned 64 bit type is unsigned long long int. However, the uint64_t typedef from stdint.h is mapped to to GCC built-in define __UINT64_TYPE__.

#define __UINT64_TYPE__ long unsigned int;

This definition is obtained by running gcc -dM -E an_empty_file.c | grep "__UINT64_TYPE__"

Of course, replacing the uint64_t with an unsigned long long int avoids the compile error. But the two types are identical on the LP64 data model.

Shouldn't this work by default?

1
static_assert(std::is_same_v<uint64_t, unsigned long long>); triggers though.Barry

1 Answers

3
votes

Shouldn't this work by default?

Nope. That standard mandates that the type of the user defined literal be unsigned long long int[1]. A long unsigned int is not the same thing, it is its own distinct type. Even if they have the exact same properties, std::is_same_v<unsigned long long int, long unsigned int> is false.

You must use a type that is unsigned long long int if you want to take an integer number for your literal.