# C++ Equivalents for PHP Scalar Types When Using `use native_types` in TypePHP

> Discover C++ equivalents for PHP scalar types with TypePHP's native_types. Learn how int, float, and bool map to C++ for optimal performance and explore high-precision type handling.

- Repository: [Swoole Project/typephp](https://github.com/swoole/typephp)
- Tags: deep-dive
- Published: 2026-08-30

---

**When you enable `use native_types` in TypePHP, scalar PHP types `int`, `float`, and `bool` compile directly to C++ `php::Int`, `php::Float`, and `php::Bool` for high-performance execution, while high-precision types like `bigInt` and `decimal` use boxed `php::Var` wrappers around GMP and libmpdec.**

The `use native_types` directive in the swoole/typephp repository triggers the AOT compiler to bypass the traditional ZVAL abstraction for specific PHP scalars, emitting native C++ arithmetic operations instead. This approach reduces memory overhead and eliminates dynamic type-checking overhead for numeric-intensive workloads. Understanding the exact mapping between PHP type declarations and their C++ equivalents is essential for optimizing performance-critical applications.

## Native Scalar Type Mappings

The following PHP scalar types receive direct C++ equivalents when native types are enabled, bypassing the Zend virtual machine's zval container.

### Integer and Floating-Point Types

The PHP `int` type compiles to **`php::Int`**, which is implemented as `zend_long` (an 8-byte signed integer, typically `int64_t`). The PHP `float` type becomes **`php::Float`**, backed by the C++ `double` type (8 bytes).

These types reside in the `php` namespace defined in [`src/phpx.h`](https://github.com/swoole/typephp/blob/main/src/phpx.h). The compiler generates straight C++ arithmetic instructions without ZVAL indirection, resulting in single-instruction addition or multiplication rather than function calls into the Zend engine.

### Boolean Types

The PHP `bool` type maps to **`php::Bool`**, implemented as the C++ primitive `bool` (1 byte). Unlike traditional PHP where booleans reside inside zval containers with type tags, native booleans use standard processor registers and memory layouts, enabling branch prediction optimizations and reducing memory footprint by 7x compared to ZVAL-based storage.

## High-Precision and Boxed Numeric Types

PHP's dynamic precision limitations are addressed through high-precision numeric types that, while native to C++ libraries, remain boxed within the PHP runtime's variant system.

### BigInt, Decimal, and BigFloat Implementation

Three high-precision types are supported but use a different compilation strategy:

- **`bigInt`** compiles to `php::Var` (Box\<BigInt\>), wrapping GMP's `mpz_class` (~32 bytes+)
- **`decimal`** compiles to `php::Var` (Box\<Decimal\>), wrapping libmpdec's `Decimal` (~64 bytes+)
- **`bigFloat`** compiles to `php::Var` (Box\<BigFloat\>), wrapping MPFR's `mpfr_t` (~32 bytes+)

These types are defined in [`src/phpx_big_int.h`](https://github.com/swoole/typephp/blob/main/src/phpx_big_int.h), [`src/phpx_decimal.h`](https://github.com/swoole/typephp/blob/main/src/phpx_decimal.h), and [`src/phpx_big_float.h`](https://github.com/swoole/typephp/blob/main/src/phpx_big_float.h) respectively. While they cannot use raw C++ register arithmetic due to their arbitrary precision requirements, they avoid PHP's string-based number handling by interfacing directly with high-performance mathematical libraries.

## Type Semantics and Compilation Rules

The TypePHP compiler enforces strict semantics when mixing native types to maintain performance guarantees.

### Arithmetic Behavior and Type Coercion

Native-type arithmetic follows pure C++ semantics. For example, the operation `int += float` truncates the float to an integer before addition, unlike PHP's standard behavior of converting the integer to float and performing floating-point addition. This behavior is documented in [`docs/en/NATIVE_TYPES.md`](https://github.com/swoole/typephp/blob/main/docs/en/NATIVE_TYPES.md).

High-precision types cannot be combined with ordinary scalars without explicit conversion. Attempting to add a `php::Int` directly to a `bigInt` triggers a compile-time error, requiring developers to use explicit constructor calls like `std::bigInt($value)`.

### Object Property Constraints

Object properties declared with native scalar types are **fixed-type** for the object's lifetime. A property declared as `public int $value` cannot be unset or assigned `null` unless explicitly marked nullable with `?int`. This constraint allows the compiler to reserve exactly 8 bytes for the property in the object layout, eliminating the overhead of hash table lookups for property access.

## Practical Code Examples

Simple arithmetic operations compile to direct C++ instructions:

```php
<?php
use native_types;

function add(int $a, int $b): int {
    return $a + $b;               // Compiles to php::Int addition (int64_t)
}

function mix(int $i, float $f): float {
    return $i + $f;               // Both operands promoted to php::Float (double)
}

```

The generated C++ implementation eliminates all ZVAL manipulation:

```cpp
php::Int add(php::Int a, php::Int b) {
    return a + b;                 // Direct int64_t addition
}
php::Float mix(php::Int i, php::Float f) {
    return static_cast<double>(i) + f; // Double addition
}

```

High-precision types require wrapper calls while maintaining mathematical accuracy:

```php
<?php
use native_types;

$big = std::bigInt("123456789012345678901234567890");
$dec = std::decimal("12345.6789");
$flt = std::bigFloat(3.1415926535);

$sum = $big + $big;               // → php::BigInt::add(...)
$ratio = $dec / std::decimal("2"); // → php::Decimal::div(...)
$pi2 = $flt * std::bigFloat(2);   // → php::BigFloat::mul(...)

```

Object properties enforce type constraints at compile time:

```php
<?php
use native_types;

class Counter {
    public int $value = 0;   // Fixed-type native int
}
$cnt = new Counter();
$cnt->value = 5;            // OK
// $cnt->value = null;      // ❌ Compile error – cannot change int to null

```

## Reference Implementation and Source Files

According to the swoole/typephp source code, the following files define the type system architecture:

- **[`docs/en/NATIVE_TYPES.md`](https://github.com/swoole/typephp/blob/main/docs/en/NATIVE_TYPES.md)** — Official documentation specifying the PHP-to-C++ type mapping and semantic rules
- **[`src/phpx.h`](https://github.com/swoole/typephp/blob/main/src/phpx.h)** — Defines `php::Int`, `php::Float`, `php::Bool`, and the `php::Variant` wrapper class used for boxed types
- **[`src/phpx_big_int.h`](https://github.com/swoole/typephp/blob/main/src/phpx_big_int.h)** — C++ wrapper around GMP providing the `Box<BigInt>` implementation
- **[`src/phpx_decimal.h`](https://github.com/swoole/typephp/blob/main/src/phpx_decimal.h)** — C++ wrapper around libmpdec providing the `Box<Decimal>` implementation
- **[`src/phpx_big_float.h`](https://github.com/swoole/typephp/blob/main/src/phpx_big_float.h)** — C++ wrapper around MPFR providing the `Box<BigFloat>` implementation

## Summary

- **Native scalars**: PHP `int`, `float`, and `bool` map to `php::Int`, `php::Float`, and `php::Bool` (C++ `int64_t`, `double`, and `bool`), eliminating ZVAL overhead.
- **Boxed precision**: `bigInt`, `decimal`, and `bigFloat` use `php::Var` wrappers around GMP, libmpdec, and MPFR libraries for arbitrary precision arithmetic.
- **C++ semantics**: Native-type arithmetic follows C++ rules (e.g., truncation on mixed int/float operations), not PHP's dynamic juggling.
- **Fixed properties**: Object properties with native types cannot be reassigned to incompatible types or null unless explicitly nullable.
- **Documentation**: Detailed mapping specifications reside in [`docs/en/NATIVE_TYPES.md`](https://github.com/swoole/typephp/blob/main/docs/en/NATIVE_TYPES.md) within the swoole/typephp repository.

## Frequently Asked Questions

### What happens to PHP strings and arrays when using `use native_types`?

Standard PHP types including `string`, `array`, `object`, and `mixed` continue to use the traditional ZVAL-based representations (`php::Str`, `php::Array`, `php::Object`, `php::Var`). Only the scalar numeric types and booleans receive the native C++ optimization treatment.

### Can I mix native `int` types with high-precision `bigInt` in arithmetic operations?

No, the TypePHP compiler raises a compile-time error when attempting to mix native scalars with high-precision types directly. You must explicitly convert native types using constructors like `std::bigInt($nativeInt)` before performing arithmetic between these categories.

### Does `use native_types` change the memory layout of PHP objects?

Yes, object properties declared with native scalar types are stored as fixed-size C++ primitives (8 bytes for int/float, 1 byte for bool) directly in the object structure, rather than as pointers to zval containers. This reduces memory usage and improves cache locality for numeric-heavy classes.

### Where is the complete type mapping documented?

The canonical reference for all PHP-to-C++ type mappings and semantic rules is located at [`docs/en/NATIVE_TYPES.md`](https://github.com/swoole/typephp/blob/main/docs/en/NATIVE_TYPES.md) in the swoole/typephp repository. This file specifies the behavior of arithmetic operations, nullable type syntax, and integration with the underlying GMP, libmpdec, and MPFR libraries.