Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add .ccm, .cxxm, .c++m extensions for C++ #7007

Closed
wants to merge 1 commit into from
Closed
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
5 changes: 4 additions & 1 deletion lib/linguist/languages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -772,12 +772,15 @@ C++:
aliases:
- cpp
extensions:
- ".cpp"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like you missed the comment right at the top of this file:

# extensions - An Array of associated extensions (the first one is
# considered the primary extension, the others should be
# listed alphabetically)

If .c++ is now considered the primary extension for the language, then this change is fine, but if it's not (which I suspect is the case) .cpp needs to remain the first extension in the list.

- ".c++"
- ".c++m"
- ".cc"
- ".ccm"
- ".cp"
- ".cpp"
- ".cppm"
- ".cxx"
- ".cxxm"
- ".h"
- ".h++"
- ".hh"
Expand Down
143 changes: 143 additions & 0 deletions samples/C++/mathematics.ccm
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/// @module mathematics
/// A sample library containing math functions.
/// A documentation comment for the file like this one must be in any file you wish to be tracked by Doxygen.

module;

#include <cmath>
#include <compare>
#include <concepts>

#include <spdlog/fmt/fmt.h>

export module mathematics;

export namespace math
{
/// A 2-dimensional mathematical vector
class Vec2
{
/// The x component of the vector (regular doc comment)
double x_{};
double y_{}; ///< The y component of the vector (postfix doc comment)

public:
/// Construct a new @ref Vec2 with the given components.
/// @param[in] _x The x component
/// @param[in] _y The y component
constexpr Vec2(double _x, double _y)
: x_{_x}, y_{_y}
{
}

/// @name Rule of 5 special member functions
///@{
/// This is a member group. Documentation comments here will be shared for all elements in the group.

constexpr ~Vec2() = default;

constexpr Vec2(const Vec2 &other) noexcept = default;

constexpr Vec2(Vec2 &&other) noexcept = default;

[[maybe_unused]]
auto constexpr operator=(Vec2 const &other) noexcept -> Vec2 & = default;

[[maybe_unused]]
auto constexpr operator=(Vec2 &&other) noexcept -> Vec2 & = default;

///@}

/// @name Getters
///@{
/// Getters for each component of the vector
[[nodiscard]]
auto constexpr x(this auto const &self) noexcept -> double
{
return self.x_;
}

[[nodiscard]]
auto constexpr y(this auto const &self) noexcept -> double
{
return self.y_;
}

///@}

/// Compute the dot product of this vector and @p other
/// @param[in] other The second operand of the dot product operator
[[nodiscard]]
auto constexpr dot(this auto const &self, Vec2 const &other) noexcept -> double
{
return self.x_ * other.x_ + self.y_ * other.y_;
}

/// Compute the norm of this vector
[[nodiscard]]
auto constexpr norm(this auto const &self) noexcept -> double
{
return std::sqrt(self.dot(self));
}

/// Compare this vector and @p other by norm
[[nodiscard]]
auto constexpr operator<=>(this auto const &self, Vec2 const &other) noexcept -> std::weak_ordering
{
return std::weak_order(self.norm(), other.norm());
}

/// Compute the scalar product of this vector and @p c
/// @param[in] c The scalar
[[nodiscard]]
auto constexpr operator*(this auto const &self, double c) noexcept -> Vec2
{
return Vec2{c * self.x(), c * self.y()};
}
};

auto constexpr operator*(double c, Vec2 const &vec) noexcept -> Vec2
{
return vec * c;
}

/// Evaluate the approximate derivative of @p f at @p x
/// @tparam f A function @f$ f : \mathbb R \to \mathbb R @f$
/// @param[in] x The x-value to evaluate the derivative at
///
/// Example: @f$ f(x) = x^2 @f$
/// @code{.cpp}
/// auto f{[](double x) { return x * x; }};
/// std::cout << d_dx<f>(3.0) << '\n'; // Prints 6
/// @endcode
template<auto f>
requires requires(double x)
{
{ f(x) } -> std::same_as<double>;
}
[[nodiscard]]
auto constexpr d_dx(double x) -> double
{
static constexpr double dx{0.00001};
return (f(x + dx) - f(x)) / dx;
}
}

/// Formatter specialization for @ref math::Vec2
export
template<>
struct fmt::formatter<math::Vec2>
{
[[nodiscard]]
auto constexpr parse(format_parse_context &ctx) -> format_parse_context::iterator
{
return ctx.end();
}

/// This function will be implemented in the implementation file.
[[nodiscard]]
auto format(math::Vec2 const &vec, fmt::format_context &ctx) -> decltype(ctx.out())
{
return fmt::format_to(ctx.out(), "({}, {})", vec.x(), vec.y());
}
};
57 changes: 57 additions & 0 deletions samples/C++/timer.c++m
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
module;

#include <functional>
#include <iostream>
#include <thread>

#include <boost/asio.hpp>

export module timer;

class Printer {
public:
explicit Printer(boost::asio::io_context& io)
: strand{boost::asio::make_strand(io)},
timer1{io, boost::asio::chrono::seconds{1}},
timer2{io, boost::asio::chrono::seconds{1}} {
this->timer1.async_wait(boost::asio::bind_executor(this->strand, std::bind(&Printer::print1, this)));
this->timer2.async_wait(boost::asio::bind_executor(this->strand, std::bind(&Printer::print2, this)));
}

~Printer() {
std::cout << "Final count is " << this->count << std::endl;
}

auto print1() -> void {
if (this->count >= 10) {
return;
}

std::cout << "Timer 1: " << this->count << std::endl;

++this->count;

this->timer1.expires_at(this->timer1.expiry() + boost::asio::chrono::seconds{1});

this->timer1.async_wait(boost::asio::bind_executor(this->strand, std::bind(&Printer::print1, this)));
}

auto print2() -> void {
if (this->count >= 10) {
return;
}

std::cout << "Timer 2: " << this->count << std::endl;

++this->count;

this->timer2.expires_at(this->timer2.expiry() + boost::asio::chrono::seconds{1});

this->timer2.async_wait(boost::asio::bind_executor(this->strand, std::bind(&Printer::print2, this)));
}

private:
boost::asio::strand<boost::asio::io_context::executor_type> strand;
boost::asio::steady_timer timer1, timer2;
int count{0};
};
116 changes: 116 additions & 0 deletions samples/C++/visitor.cxxm
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
export module main;

import std;

struct A;
struct B;
struct C;

using NodeVariant = std::variant<A, B, C>;
using Children = std::vector<NodeVariant>;

struct Node
{
Children children{};
};

struct A : Node
{
};

struct B : Node
{
};

struct C : Node
{
};

class PrintVisitor
{
struct ScopedDepth
{
std::size_t &depth;

constexpr ScopedDepth(std::size_t &depth) noexcept : depth{depth}
{
++this->depth;
}

constexpr ~ScopedDepth()
{
--this->depth;
}
};

std::size_t depth{0};

auto print(this auto const &self, std::string_view str) -> void
{
constexpr auto indent_spaces{4u};
auto const indentation{self.depth * indent_spaces};

std::println("{}{}", std::string(indentation, ' '), str);
}

auto recurse(this auto &self, std::span<NodeVariant const> children) -> void
{
std::ranges::for_each(
children,
[&](NodeVariant const &node)
{
std::visit(self, node);
}
);
}

public:

auto operator()(this auto &self, A const &node) -> void
{
self.print("A");
ScopedDepth depth{self.depth};
self.recurse(node.children);
}

template <typename T>
requires std::same_as<T, B> or std::same_as<T, C>
auto operator()(this auto &self, T const &node) -> void
{
self.print("B|C");
ScopedDepth depth{self.depth};
self.recurse(node.children);
}

auto operator()(this auto const &self, auto const &other) -> void
{
std::println("Unknown type: {}", typeid(other).name());
}
};

auto main() -> int
{
NodeVariant root{A{Children{
B{Children{
C{},
B{},
A{}
}},
A{},
A{Children{
B{},
C{}
}},
B{Children{
C{Children{
A{},
B{},
B{},
C{}
}}
}}
}}};

PrintVisitor visitor{};
std::visit(visitor, root);
}