Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ jobs:
- name: Run all Rust binaries
# If we ever add more than two binaries, detect them all automatically
run: |
cargo run --bin cpp-string-overload
cargo run --bin rust-string-overload
cargo run --bin cpp-pow-overload
cargo run --bin rust-pow-overload

clippy-rust:
name: 4. Clippy lints on Rust crates
Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
[workspace]
resolver = "3"
members = [
"cpp-string-overload",
"cpp-pow-overload",
]
default-members = [
"cpp-string-overload",
"cpp-pow-overload",
]

[workspace.package]
Expand All @@ -18,7 +18,7 @@ keywords = [
"overload",
"C++",
"interop",
"example",
"splat",
]
license = "MIT OR APACHE-2.0"
readme = "README.md"
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ git clone https://github.com/rustfoundation/overloading-examples
cd overloading-examples
rustup override set nightly
cargo run
cargo run --bin rust-string-overload
cargo run --bin rust-pow-overload
```
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# Modify the workspace Cargo.toml instead of this file (if possible)
[package]
name = "cpp-string-overload"
default-run = "cpp-string-overload"
name = "cpp-pow-overload"
default-run = "cpp-pow-overload"

version.workspace = true
authors.workspace = true
edition.workspace = true
Expand Down
3 changes: 3 additions & 0 deletions cpp-pow-overload/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() {
cpp_build::build("src/bin/cpp-pow-overload.rs");
}
83 changes: 83 additions & 0 deletions cpp-pow-overload/src/bin/cpp-pow-overload.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
//! Example of calling overloaded C++ arithmetic functions from Rust.

#![feature(splat, tuple_trait)]
#![expect(incomplete_features)]

use cpp::cpp;
use std::ffi::{c_double, c_float, c_int};
use std::marker::Tuple;

cpp! {{
#include <cmath>
#include <iostream>
}}

/// The arguments of an overloaded C++ `pow` function.
trait PowArgs: Tuple {
type Output;
fn call_pow(self) -> Self::Output;
}

/// Calls the overloaded C++ `std::pow` function with the given arguments.
fn pow<Args: PowArgs>(#[splat] args: Args) -> <Args as PowArgs>::Output {
args.call_pow()
}

impl PowArgs for (c_float, c_float) {
type Output = c_float;

fn call_pow(self) -> c_float {
let (base, exponent) = self;
unsafe {
cpp!([base as "float", exponent as "float"] -> c_float as "float" {
return std::pow(base, exponent);
})
}
}
}

impl PowArgs for (c_double, c_double) {
type Output = c_double;

fn call_pow(self) -> c_double {
let (base, exponent) = self;
unsafe {
cpp!([base as "double", exponent as "double"] -> c_double as "double" {
return std::pow(base, exponent);
})
}
}
}

impl PowArgs for (c_float, c_int) {
type Output = c_float;

fn call_pow(self) -> c_float {
let (base, exponent) = self;
unsafe {
cpp!([base as "float", exponent as "int"] -> c_float as "float" {
return std::pow(base, exponent);
})
}
}
}

impl PowArgs for (c_int, c_int) {
type Output = c_double;

fn call_pow(self) -> c_double {
let (base, exponent) = self;
unsafe {
cpp!([base as "int", exponent as "int"] -> c_double as "double" {
// C++ casts to `double` before calling `std::pow<double>`
return std::pow(base, exponent);
})
}
}
}

fn main() {
println!("2^3 f32 = {}", pow(2.0_f32, 3.0_f32));
println!("2^3 f64 = {}", pow(2.0_f64, 3.0_f64));
println!("2^3 i32 = {}", pow(2_i32, 3_i32));
}
51 changes: 51 additions & 0 deletions cpp-pow-overload/src/bin/rust-pow-overload.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//! Example of Rust arithmetic via overloaded functions.

#![feature(splat, tuple_trait)]
#![expect(incomplete_features)]

use std::marker::Tuple;

/// The arguments of an overloaded Rust power function.
trait PowArgs: Tuple {
type Output;
fn call_pow(self) -> Self::Output;
}

/// Calls the specific Rust power function with the given arguments.
fn pow<Args: PowArgs>(#[splat] args: Args) -> <Args as PowArgs>::Output {
args.call_pow()
}

impl PowArgs for (f32, f32) {
type Output = f32;

fn call_pow(self) -> f32 {
let (base, exponent) = self;
base.powf(exponent)
}
}

impl PowArgs for (f64, f64) {
type Output = f64;

fn call_pow(self) -> f64 {
let (base, exponent) = self;
base.powf(exponent)
}
}

impl PowArgs for (i32, u32) {
type Output = i32;

fn call_pow(self) -> i32 {
let (base, exponent) = self;
// Rust does the calculations in integer arithmetic
base.pow(exponent)
}
}

fn main() {
println!("2^3 f32 = {}", pow(2.0_f32, 3.0_f32));
println!("2^3 f64 = {}", pow(2.0_f64, 3.0_f64));
println!("2^3 i32 = {}", pow(2_i32, 3_u32));
}
3 changes: 0 additions & 3 deletions cpp-string-overload/build.rs

This file was deleted.

15 changes: 0 additions & 15 deletions cpp-string-overload/src/bin/cpp-string-overload.rs

This file was deleted.

3 changes: 0 additions & 3 deletions cpp-string-overload/src/bin/rust-string-overload.rs

This file was deleted.