0

I am having troubles with long type on macOS ( Apple clang version 13.1.6, arm64-apple-darwin21.6.0 ) with the following code:

#include <iostream>
#include <cstdint>

void call_int64( std::int64_t& v )
{
   std::cout << "v = " << v << std::endl;
}

void call_int32( std::int32_t& v )
{
   std::cout << "v = " << v << std::endl;
}

void call_int16( std::int16_t& v )
{
   std::cout << "v = " << v << std::endl;
}

int main()
{
   long a = 0;
   call_int16( a );
   call_int32( a );
   call_int64( a );
   return 0;
}

which results in:

test-long-2.cpp:22:4: error: no matching function for call to 'call_int16'
   call_int16( a );
   ^~~~~~~~~~
test-long-2.cpp:14:6: note: candidate function not viable: no known conversion from 'long' to 'std::int16_t &' (aka 'short &') for 1st argument
void call_int16( std::int16_t& v )
     ^
test-long-2.cpp:23:4: error: no matching function for call to 'call_int32'
   call_int32( a );
   ^~~~~~~~~~
test-long-2.cpp:9:6: note: candidate function not viable: no known conversion from 'long' to 'std::int32_t &' (aka 'int &') for 1st argument
void call_int32( std::int32_t& v )
     ^
test-long-2.cpp:24:4: error: no matching function for call to 'call_int64'
   call_int64( a );
   ^~~~~~~~~~
test-long-2.cpp:4:6: note: candidate function not viable: no known conversion from 'long' to 'std::int64_t &' (aka 'long long &') for 1st argument
void call_int64( std::int64_t& v )
     ^
3 errors generated.

So it seems that long cannot be converted to any std integral type. On linux, I am getting only two errors, long is accepted by call_int64.

  • There's no problem converting `long` to any other integral type. But that's not what the code is trying to do, and that's not what the compiler is complaining about. The code attempts to convert a `long&` (i.e., **reference** to `long`) into an `int16_t&` (i.e., **reference** to `int16_t`). – Pete Becker Aug 18 '22 at 16:56

1 Answers1

0

There is no guarantee that long is aliased to any of the std::intX_t type aliases. Relying on that is wrong. The concrete choices for the aliases std::intX_t are implementation-defined and can vary between compilers, platform, standard library implementation, etc.

On many platforms long and long long are both 64bit types and in64_t will alias only one of them. The other one will not have any intX_t alias in that case.

The types long and long long are different types even if they have the same size, alignment and representation and therefore an object of one of these types cannot bind a reference of the other type.

Because the references you are using are non-const lvalue references conversions from one of these types to the other are also not considered (and if they were, the result would be that the references bind to temporary objects created in the conversion, not the object passed as argument).

user17732522
  • 53,019
  • 2
  • 56
  • 105