8

I have some headache inducing problems here.

Basically I'm trying to make a library compatible with different Arduino systems (not an Arduino question).

I have a situation where types no longer match, as in an int is no longer equivalent to its identical fixed width type. In the limited environment provided (no stdlib and such) I have written my own type trait classes for the features I need.

Everything works fine using GCC 4.8.1 (avr) & Extensa-1x106-GCC (ESP8266), but not in GCC 4.8.3 (SAM,SAMD cores).

Basically I have knuckled down my code to show the problem in this very basic code (int is confirmed to have 4 bytes on the failing 32-bit platform compilers):

template < typename T, typename U > struct is_same{ enum { value = false }; };
template < typename T > struct is_same< T, T >    { enum { value = true }; };

void setup() {
  static_assert( is_same<int,int32_t>::value, "Not integer");
}

void loop(){}

You can view a 'normal' C++ implementation here (above is a basic implementation for use within the Arduino IDE): http://cpp.sh/377e

By the way, the static assert does not fire in the cpp.sh compiler either.

Is 4.8.1 incorrect, meaning int and int32_t should be considered different types. Or is 4.8.3 incorrect and they should be equivalent if equally sized defined by the implementation.

I was using the code below to detect any type of integer, which was where I found my error originally.

template< typename T >
    struct is_integer{
        enum{
            V8    = is_same< T, uint8_t >::value  || is_same< T, int8_t >::value,
            V16   = is_same< T, uint16_t >::value || is_same< T, int16_t >::value,
            V32   = is_same< T, uint32_t >::value || is_same< T, int32_t >::value,
            V64   = is_same< T, uint64_t >::value || is_same< T, int64_t >::value,
            value = V8 || V16 || V32 || V64
        };
};

I of course can change it to check for char, int, long, etc.. but it will still require checking for all fixed width variations and most likely the int_fastX_t and int_leastX_t types, which seems like a super redundant method to ensure maximum usability.

Any ideas?

Cheers, I appreciate any input!

4

2 回答 2

5

这受 C 标准的约束;C++ 只是通过显式引用继承行为。

C标准说的是:

  • 如果int32_t已定义,则它指的是带符号的 32 位 2 的补码整数。

  • 如果实现提供带符号的 32 位 2 的补码整数类型,则它必须提供int32_t引用它的 typedef。

它没有说这个 32 位 2 的补码有符号整数类型必须是int. 从技术上讲,即使int 32 位 2 的补码整数类型,实现也完全有可能提供不同的 32 位 2 的补码有符号整数类型并定义int32_t为引用该其他类型。

恐怕唯一完全通用的解决方案是列出所有基本类型、固定宽度类型、最小宽度类型和快速最小宽度类型。

对于不那么令人生畏的事情,应该可以检查您希望支持的工具链的文档,以找到它们提供的类型以及它们的命名方式。如果这组“您希望支持的工具链”是无限的,我认为没有更简单的出路。

于 2015-09-28T12:00:11.143 回答
1

来自 C11 标准 7.20.1.1(1)

typedef 名称 intN_t 指定宽度为 N、无填充位和二进制补码表示的有符号整数类型。因此, int8_t 表示这种宽度正好为 8 位的有符号整数类型。

int32_t正好是 32 位宽的有符号整数也是如此。

int虽然定义为sizeof(int)大于或等于(C++14 3.9.1(2)) 并且带符号的charint 必须能够表示[-32767, 32767](C11 5.2.4.2.1)。该范围实际上是 16 位。

因此,anint可能永远不会等同于 a intN_t,因为 anintN_t可以是与标准类型分开的实现定义类型。

于 2015-09-28T12:01:23.260 回答