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
12 changes: 12 additions & 0 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
Language: Cpp
BasedOnStyle: LLVM
IndentWidth: 2
ColumnLimit: 80
AllowShortBlocksOnASingleLine: Never
AllowShortFunctionsOnASingleLine: All
AllowShortEnumsOnASingleLine: true
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AllowShortLambdasOnASingleLine: All
AlwaysBreakTemplateDeclarations: MultiLine
16 changes: 13 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,18 @@ jobs:
sudo apt-get install -y --no-install-recommends \
cmake \
ninja-build \
clang-format \
clang-tidy

- name: Install clang-format 18
shell: bash
run: |
set -euo pipefail
wget -qO /tmp/llvm.sh https://apt.llvm.org/llvm.sh
sudo bash /tmp/llvm.sh 18
sudo apt-get install -y --no-install-recommends clang-format-18
sudo ln -sf /usr/bin/clang-format-18 /usr/local/bin/clang-format
clang-format --version

- name: Set up Rust (stable)
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
Expand All @@ -46,7 +55,7 @@ jobs:
shell: bash
run: |
set -euo pipefail
cmake -S . -B build -G Ninja -DQTTY_BUILD_DOCS=OFF -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
cmake -S . -B build -G Ninja -DQTTY_BUILD_DOCS=OFF -DQTTY_FFI_FEATURES="serde" -DCMAKE_EXPORT_COMPILE_COMMANDS=ON

- name: clang-format check
shell: bash
Expand Down Expand Up @@ -147,7 +156,7 @@ jobs:
shell: bash
run: |
set -euo pipefail
cmake -S . -B build -G Ninja -DQTTY_BUILD_DOCS=ON
cmake -S . -B build -G Ninja -DQTTY_BUILD_DOCS=ON -DQTTY_FFI_FEATURES="serde"

- name: Build
shell: bash
Expand Down Expand Up @@ -205,6 +214,7 @@ jobs:
set -euo pipefail
cmake -S . -B build-coverage -G Ninja \
-DQTTY_BUILD_DOCS=OFF \
-DQTTY_FFI_FEATURES="serde" \
-DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_CXX_FLAGS="--coverage" \
-DCMAKE_EXE_LINKER_FLAGS="--coverage"
Expand Down
43 changes: 20 additions & 23 deletions examples/demo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,65 +20,62 @@ int main() {
// Example 1: Basic construction and conversion
std::cout << "1. Distance Conversion:" << std::endl;
Meter distance(1500.0);
std::cout << " Distance: " << distance.value() << " m" << std::endl;
std::cout << " Distance: " << distance << std::endl;

Kilometer km = distance.to<Kilometer>();
std::cout << " Distance: " << km.value() << " km" << std::endl;
std::cout << " Distance: " << km << std::endl;

// Example 2: Using literals
std::cout << "\n2. Using Literals:" << std::endl;
auto height = 10.5_m;
auto width = 5.0_m;
auto area_side = height + width;
std::cout << " Height: " << height.value() << " m" << std::endl;
std::cout << " Width: " << width.value() << " m" << std::endl;
std::cout << " Sum: " << area_side.value() << " m" << std::endl;
std::cout << " Height: " << height << std::endl;
std::cout << " Width: " << width << std::endl;
std::cout << " Sum: " << area_side << std::endl;

// Example 3: Velocity calculation
std::cout << "\n3. Velocity Calculation:" << std::endl;
auto car_distance = 100.0_km;
auto travel_time = 2.0_h;
auto speed = car_distance / travel_time;
std::cout << " Distance: " << car_distance.value() << " km" << std::endl;
std::cout << " Time: " << travel_time.value() << " h" << std::endl;
std::cout << " Speed: " << speed.value() << " km/h" << std::endl;
std::cout << " Distance: " << car_distance << std::endl;
std::cout << " Time: " << travel_time << std::endl;
std::cout << " Speed: " << speed << std::endl;

// Example 4: Angular conversions
std::cout << "\n4. Angular Conversions:" << std::endl;
auto angle_deg = 180.0_deg;
Radian angle_rad = angle_deg.to<Radian>();
std::cout << " Angle: " << angle_deg.value() << " degrees" << std::endl;
std::cout << " Angle: " << angle_deg << std::endl;
std::cout << std::setprecision(6);
std::cout << " Angle: " << angle_rad.value() << " radians" << std::endl;
std::cout << " Angle: " << angle_rad << std::endl;

// Example 5: Time conversions
std::cout << "\n5. Time Conversions:" << std::endl;
auto duration_seconds = 3665.0_s;
Hour duration_hours = duration_seconds.to<Hour>();
Minute duration_minutes = duration_seconds.to<Minute>();
std::cout << " Duration: " << duration_seconds.value() << " seconds"
<< std::endl;
std::cout << " Duration: " << duration_seconds << std::endl;
std::cout << std::setprecision(4);
std::cout << " Duration: " << duration_hours.value() << " hours"
<< std::endl;
std::cout << " Duration: " << duration_hours << std::endl;
std::cout << std::setprecision(2);
std::cout << " Duration: " << duration_minutes.value() << " minutes"
<< std::endl;
std::cout << " Duration: " << duration_minutes << std::endl;

// Example 6: Compound operations
std::cout << "\n6. Compound Operations:" << std::endl;
Meter total(100.0);
std::cout << " Initial: " << total.value() << " m" << std::endl;
std::cout << " Initial: " << total << std::endl;

total += 50.0_m;
std::cout << " After += 50m: " << total.value() << " m" << std::endl;
std::cout << " After += 50m: " << total << std::endl;

total *= 2.0;
std::cout << " After *= 2: " << total.value() << " m" << std::endl;
std::cout << " After *= 2: " << total << std::endl;

total /= 3.0;
std::cout << std::setprecision(2) << std::fixed;
std::cout << " After /= 3: " << total.value() << " m" << std::endl;
std::cout << " After /= 3: " << total << std::endl;

// Example 7: Comparisons
std::cout << "\n7. Comparisons:" << std::endl;
Expand All @@ -94,9 +91,9 @@ int main() {
Meter negative(-42.5);
auto positive = negative.abs();
auto double_negative = -negative;
std::cout << " Original: " << negative.value() << " m" << std::endl;
std::cout << " Absolute: " << positive.value() << " m" << std::endl;
std::cout << " Negated: " << double_negative.value() << " m" << std::endl;
std::cout << " Original: " << negative << std::endl;
std::cout << " Absolute: " << positive << std::endl;
std::cout << " Negated: " << double_negative << std::endl;

std::cout << "\n=== All examples completed successfully! ===" << std::endl;

Expand Down
3 changes: 2 additions & 1 deletion gen_cpp_units.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,10 @@ def generate_header_for_dimension(dimension: str, units: List[Tuple[str, str, st

# Generate unit traits specializations
unit_traits = []
for const_name, name, _ in units:
for const_name, name, symbol in units:
unit_traits.append(f"""template<> struct UnitTraits<{name}Tag> {{
static constexpr UnitId unit_id() {{ return UNIT_ID_{const_name}; }}
static constexpr std::string_view symbol() {{ return "{symbol}"; }}
}};""")

# Generate type aliases
Expand Down
13 changes: 13 additions & 0 deletions include/qtty/ffi_core.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
*/

#include <cmath>
#include <iostream>
#include <stdexcept>
#include <string>
#include <string_view>
#include <type_traits>
extern "C" {
#include "qtty_ffi.h"
Expand Down Expand Up @@ -278,4 +280,15 @@ template <typename UnitTag> class Quantity {
Quantity abs() const { return Quantity(std::abs(m_value)); }
};

// ============================================================================
// Stream Insertion Operator
// ============================================================================
// Prints a quantity with its unit symbol, e.g., "1500 m" or "42.5 km"

template <typename UnitTag>
std::ostream &operator<<(std::ostream &os, const Quantity<UnitTag> &q) {
os << q.value() << " " << UnitTraits<UnitTag>::symbol();
return os;
}

} // namespace qtty
10 changes: 10 additions & 0 deletions include/qtty/units/angular.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,33 +20,43 @@ struct HourAngleTag {};

template <> struct UnitTraits<MilliradianTag> {
static constexpr UnitId unit_id() { return UNIT_ID_MILLIRADIAN; }
static constexpr std::string_view symbol() { return "mrad"; }
};
template <> struct UnitTraits<RadianTag> {
static constexpr UnitId unit_id() { return UNIT_ID_RADIAN; }
static constexpr std::string_view symbol() { return "rad"; }
};
template <> struct UnitTraits<MicroArcsecondTag> {
static constexpr UnitId unit_id() { return UNIT_ID_MICRO_ARCSECOND; }
static constexpr std::string_view symbol() { return "µas"; }
};
template <> struct UnitTraits<MilliArcsecondTag> {
static constexpr UnitId unit_id() { return UNIT_ID_MILLI_ARCSECOND; }
static constexpr std::string_view symbol() { return "mas"; }
};
template <> struct UnitTraits<ArcsecondTag> {
static constexpr UnitId unit_id() { return UNIT_ID_ARCSECOND; }
static constexpr std::string_view symbol() { return "″"; }
};
template <> struct UnitTraits<ArcminuteTag> {
static constexpr UnitId unit_id() { return UNIT_ID_ARCMINUTE; }
static constexpr std::string_view symbol() { return "′"; }
};
template <> struct UnitTraits<DegreeTag> {
static constexpr UnitId unit_id() { return UNIT_ID_DEGREE; }
static constexpr std::string_view symbol() { return "°"; }
};
template <> struct UnitTraits<GradianTag> {
static constexpr UnitId unit_id() { return UNIT_ID_GRADIAN; }
static constexpr std::string_view symbol() { return "gon"; }
};
template <> struct UnitTraits<TurnTag> {
static constexpr UnitId unit_id() { return UNIT_ID_TURN; }
static constexpr std::string_view symbol() { return "tr"; }
};
template <> struct UnitTraits<HourAngleTag> {
static constexpr UnitId unit_id() { return UNIT_ID_HOUR_ANGLE; }
static constexpr std::string_view symbol() { return "ʰ"; }
};

using Milliradian = Quantity<MilliradianTag>;
Expand Down
Loading