From 8e200130ec2b75fc532d9d5fe05e3e744bef3ecc Mon Sep 17 00:00:00 2001 From: teor Date: Fri, 10 Jul 2026 15:36:03 +1000 Subject: [PATCH 1/2] Use std::pow because it's simpler --- .github/workflows/check.yml | 4 +- Cargo.lock | 2 +- Cargo.toml | 6 +- README.md | 2 +- .../Cargo.toml | 5 +- cpp-pow-overload/build.rs | 3 + cpp-pow-overload/src/bin/cpp-pow-overload.rs | 83 +++++++++++++++++++ .../src/bin/rust-pow-overload.rs | 0 cpp-string-overload/build.rs | 3 - .../src/bin/cpp-string-overload.rs | 15 ---- 10 files changed, 96 insertions(+), 27 deletions(-) rename {cpp-string-overload => cpp-pow-overload}/Cargo.toml (85%) create mode 100644 cpp-pow-overload/build.rs create mode 100644 cpp-pow-overload/src/bin/cpp-pow-overload.rs rename cpp-string-overload/src/bin/rust-string-overload.rs => cpp-pow-overload/src/bin/rust-pow-overload.rs (100%) delete mode 100644 cpp-string-overload/build.rs delete mode 100644 cpp-string-overload/src/bin/cpp-string-overload.rs diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 63f8a71..b95d9e8 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -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 diff --git a/Cargo.lock b/Cargo.lock index e5246d4..ae096cb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -37,7 +37,7 @@ dependencies = [ ] [[package]] -name = "cpp-string-overload" +name = "cpp-pow-overload" version = "0.0.0" dependencies = [ "cpp", diff --git a/Cargo.toml b/Cargo.toml index 3cfd34f..78a0baa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,10 +1,10 @@ [workspace] resolver = "3" members = [ - "cpp-string-overload", + "cpp-pow-overload", ] default-members = [ - "cpp-string-overload", + "cpp-pow-overload", ] [workspace.package] @@ -18,7 +18,7 @@ keywords = [ "overload", "C++", "interop", - "example", + "splat", ] license = "MIT OR APACHE-2.0" readme = "README.md" diff --git a/README.md b/README.md index 6427d92..10a5a8d 100644 --- a/README.md +++ b/README.md @@ -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 ``` diff --git a/cpp-string-overload/Cargo.toml b/cpp-pow-overload/Cargo.toml similarity index 85% rename from cpp-string-overload/Cargo.toml rename to cpp-pow-overload/Cargo.toml index faf91b1..b9151cd 100644 --- a/cpp-string-overload/Cargo.toml +++ b/cpp-pow-overload/Cargo.toml @@ -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 diff --git a/cpp-pow-overload/build.rs b/cpp-pow-overload/build.rs new file mode 100644 index 0000000..8e621d1 --- /dev/null +++ b/cpp-pow-overload/build.rs @@ -0,0 +1,3 @@ +fn main() { + cpp_build::build("src/bin/cpp-pow-overload.rs"); +} diff --git a/cpp-pow-overload/src/bin/cpp-pow-overload.rs b/cpp-pow-overload/src/bin/cpp-pow-overload.rs new file mode 100644 index 0000000..ebf7516 --- /dev/null +++ b/cpp-pow-overload/src/bin/cpp-pow-overload.rs @@ -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 + #include +}} + +/// 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(#[splat] args: Args) -> ::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` + 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)); +} diff --git a/cpp-string-overload/src/bin/rust-string-overload.rs b/cpp-pow-overload/src/bin/rust-pow-overload.rs similarity index 100% rename from cpp-string-overload/src/bin/rust-string-overload.rs rename to cpp-pow-overload/src/bin/rust-pow-overload.rs diff --git a/cpp-string-overload/build.rs b/cpp-string-overload/build.rs deleted file mode 100644 index f793c81..0000000 --- a/cpp-string-overload/build.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - cpp_build::build("src/bin/cpp-string-overload.rs"); -} diff --git a/cpp-string-overload/src/bin/cpp-string-overload.rs b/cpp-string-overload/src/bin/cpp-string-overload.rs deleted file mode 100644 index de86ae7..0000000 --- a/cpp-string-overload/src/bin/cpp-string-overload.rs +++ /dev/null @@ -1,15 +0,0 @@ -use cpp::cpp; - -cpp! {{ - #include -}} - -fn main() { - println!("This does nothing in Rust yet"); - - unsafe { - cpp!([] -> () as "void" { - std::cout << "This does nothing in C++ yet" << std::endl; - }); - } -} From fe1a2bc6b61a672917247357b950bd1b4590ae43 Mon Sep 17 00:00:00 2001 From: teor Date: Fri, 10 Jul 2026 15:52:13 +1000 Subject: [PATCH 2/2] Add the Rust power function equivalent --- cpp-pow-overload/src/bin/rust-pow-overload.rs | 50 ++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/cpp-pow-overload/src/bin/rust-pow-overload.rs b/cpp-pow-overload/src/bin/rust-pow-overload.rs index c73ed68..4e0d66a 100644 --- a/cpp-pow-overload/src/bin/rust-pow-overload.rs +++ b/cpp-pow-overload/src/bin/rust-pow-overload.rs @@ -1,3 +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(#[splat] args: Args) -> ::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!("This does nothing in Rust yet"); + 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)); }