Skip to content

Commit 56d7737

Browse files
committed
Switch to using 2 & 3 arg hypot
1 parent 5c26d06 commit 56d7737

11 files changed

Lines changed: 161 additions & 133 deletions

File tree

.github/workflows/check.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ jobs:
5353
- name: Run all Rust binaries
5454
# If we ever add more than two binaries, detect them all automatically
5555
run: |
56-
cargo run --bin cpp-pow-overload
57-
cargo run --bin rust-pow-overload
56+
cargo run --bin cpp-hypot-overload
57+
cargo run --bin rust-hypot-overload
5858
5959
clippy-rust:
6060
name: 4. Clippy lints on Rust crates

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
[workspace]
22
resolver = "3"
33
members = [
4-
"cpp-pow-overload",
4+
"cpp-hypot-overload",
55
]
66
default-members = [
7-
"cpp-pow-overload",
7+
"cpp-hypot-overload",
88
]
99

1010
[workspace.package]

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,5 @@ git clone https://github.com/rustfoundation/overloading-examples
1212
cd overloading-examples
1313
rustup override set nightly
1414
cargo run
15-
cargo run --bin rust-pow-overload
15+
cargo run --bin rust-hypot-overload
1616
```
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Modify the workspace Cargo.toml instead of this file (if possible)
22
[package]
3-
name = "cpp-pow-overload"
4-
default-run = "cpp-pow-overload"
3+
name = "cpp-hypot-overload"
4+
default-run = "cpp-hypot-overload"
55

66
version.workspace = true
77
authors.workspace = true

cpp-hypot-overload/build.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
fn main() {
2+
cpp_build::Config::new()
3+
.flag("-std=c++17")
4+
.build("src/bin/cpp-hypot-overload.rs");
5+
}
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
//! Example of calling overloaded C++ arithmetic functions from Rust.
2+
3+
#![feature(splat, tuple_trait)]
4+
#![expect(incomplete_features)]
5+
6+
use cpp::cpp;
7+
use std::ffi::{c_double, c_int};
8+
use std::marker::Tuple;
9+
10+
cpp! {{
11+
#include <cmath>
12+
}}
13+
14+
/// The arguments of an overloaded C++ `hypot` function.
15+
trait HypotArgs: Tuple {
16+
type Output;
17+
fn call_hypot(self) -> Self::Output;
18+
}
19+
20+
/// Calls the overloaded C++ `std::hypot` function with the given arguments.
21+
fn hypot<Args: HypotArgs>(#[splat] args: Args) -> <Args as HypotArgs>::Output {
22+
args.call_hypot()
23+
}
24+
25+
impl HypotArgs for (c_double, c_double) {
26+
type Output = c_double;
27+
28+
fn call_hypot(self) -> c_double {
29+
let (x, y) = self;
30+
unsafe {
31+
cpp!([x as "double", y as "double"] -> c_double as "double" {
32+
return std::hypot(x, y);
33+
})
34+
}
35+
}
36+
}
37+
38+
impl HypotArgs for (c_double, c_double, c_double) {
39+
type Output = c_double;
40+
41+
fn call_hypot(self) -> c_double {
42+
let (x, y, z) = self;
43+
unsafe {
44+
cpp!([x as "double", y as "double", z as "double"] -> c_double as "double" {
45+
return std::hypot(x, y, z);
46+
})
47+
}
48+
}
49+
}
50+
51+
impl HypotArgs for (c_int, c_int) {
52+
type Output = c_double;
53+
54+
fn call_hypot(self) -> c_double {
55+
let (x, y) = self;
56+
unsafe {
57+
cpp!([x as "int", y as "int"] -> c_double as "double" {
58+
// C++ instantiates the `std::hypot<int, int>` template, which casts to `double`
59+
// before calling `std::hypot(double, double)`.
60+
return std::hypot(x, y);
61+
})
62+
}
63+
}
64+
}
65+
66+
impl HypotArgs for (c_int, c_int, c_int) {
67+
type Output = c_double;
68+
69+
fn call_hypot(self) -> c_double {
70+
let (x, y, z) = self;
71+
unsafe {
72+
cpp!([x as "int", y as "int", z as "int"] -> c_double as "double" {
73+
// C++ instantiates the `std::hypot<int, int, int>` template, which casts to
74+
// `double` before calling `std::hypot(double, double, double)`.
75+
return std::hypot(x, y, z);
76+
})
77+
}
78+
}
79+
}
80+
81+
fn main() {
82+
// Rust doesn't have c_* literal type specifiers.
83+
println!("|(3, 4)| double = {}", hypot(3.0_f64, 4.0_f64));
84+
println!("|(2, 3, 6)| double = {}", hypot(2.0_f64, 3.0_f64, 6.0_f64));
85+
println!("|(3, 4)| int = {}", hypot(3_i32, 4_i32));
86+
println!("|(2, 3, 6)| int = {}", hypot(2_i32, 3_i32, 6_i32));
87+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
//! Example of Rust arithmetic via overloaded functions.
2+
3+
#![feature(splat, tuple_trait)]
4+
#![expect(incomplete_features)]
5+
6+
use std::marker::Tuple;
7+
8+
/// The arguments of an overloaded Rust `hypot` function.
9+
trait HypotArgs: Tuple {
10+
type Output;
11+
fn call_hypot(self) -> Self::Output;
12+
}
13+
14+
/// Calls the overloaded Rust `hypot` function with the given arguments.
15+
fn hypot<Args: HypotArgs>(#[splat] args: Args) -> <Args as HypotArgs>::Output {
16+
args.call_hypot()
17+
}
18+
19+
impl HypotArgs for (f64, f64) {
20+
type Output = f64;
21+
22+
fn call_hypot(self) -> f64 {
23+
let (x, y) = self;
24+
x.hypot(y)
25+
}
26+
}
27+
28+
impl HypotArgs for (f64, f64, f64) {
29+
type Output = f64;
30+
31+
fn call_hypot(self) -> f64 {
32+
let (x, y, z) = self;
33+
// Rust std doesn't have a `hypot(x, y, z)` implementation.
34+
f64::sqrt(x.powi(2) + y.powi(2) + z.powi(2))
35+
}
36+
}
37+
38+
impl HypotArgs for (i32, i32) {
39+
type Output = f64;
40+
41+
fn call_hypot(self) -> f64 {
42+
let (x, y) = self;
43+
f64::from(x).hypot(f64::from(y))
44+
}
45+
}
46+
47+
impl HypotArgs for (i32, i32, i32) {
48+
type Output = f64;
49+
50+
fn call_hypot(self) -> f64 {
51+
let (x, y, z) = self;
52+
f64::sqrt(f64::from(x).powi(2) + f64::from(y).powi(2) + f64::from(z).powi(2))
53+
}
54+
}
55+
56+
fn main() {
57+
println!("|(3, 4)| f64 = {}", hypot(3.0_f64, 4.0_f64));
58+
println!("|(2, 3, 6)| f64 = {}", hypot(2.0_f64, 3.0_f64, 6.0_f64));
59+
println!("|(3, 4)| i32 = {}", hypot(3_i32, 4_i32));
60+
println!("|(2, 3, 6)| i32 = {}", hypot(2_i32, 3_i32, 6_i32));
61+
}

cpp-pow-overload/build.rs

Lines changed: 0 additions & 3 deletions
This file was deleted.

cpp-pow-overload/src/bin/cpp-pow-overload.rs

Lines changed: 0 additions & 71 deletions
This file was deleted.

0 commit comments

Comments
 (0)