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
115 changes: 115 additions & 0 deletions .github/workflows/dslings-ref-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
name: Validate dslings reference solutions

on:
push:
branches: ["main"]
paths:
- "dslings/**"
- "solutions/**"
- "d2x/**"
- "xmake.lua"
- ".github/workflows/dslings-ref-ci.yml"
pull_request:
paths:
- "dslings/**"
- "solutions/**"
- "d2x/**"
- "xmake.lua"
- ".github/workflows/dslings-ref-ci.yml"
workflow_dispatch:

jobs:
build-and-run-reference:
runs-on: ubuntu-latest

env:
XLINGS_VERSION: "0.4.3"

steps:
- uses: actions/checkout@v4

- name: Install Xlings ${{ env.XLINGS_VERSION }}
run: |
set -eu
curl -fsSL "https://github.com/d2learn/xlings/releases/download/v${XLINGS_VERSION}/xlings-${XLINGS_VERSION}-linux-x86_64.tar.gz" \
| tar -xzf - -C /tmp
/tmp/xlings-${XLINGS_VERSION}-linux-x86_64/bin/xlings self install
echo "$HOME/.xlings/subos/current/bin" >> "$GITHUB_PATH"

- name: Install xmake (via xlings)
run: xlings install xmake -y

- name: xmake config
run: xmake f -y

# Following steps go through the SAME `xmake d2x-buildtools` plugin
# path that `d2x checker` uses internally (see d2x/buildtools/xmake/main.lua).
# This way the CI exercises the real d2x integration code path, not a
# parallel xmake-only path. A passing CI here is what a learner would
# see if they ran `d2x checker cpp11-XX-feat-K-ref` locally.

- name: List all *-ref targets via d2x-buildtools
id: list_ref
run: |
set -eu
REF_TARGETS=$(xmake d2x-buildtools --command=list 2>/dev/null \
| tr ' ' '\n' \
| sed 's/@.*$//' \
| grep -E '\-ref$' \
| sort -u)
echo "Found $(echo "$REF_TARGETS" | wc -l) reference targets:"
echo "$REF_TARGETS"
echo "targets<<EOF" >> "$GITHUB_OUTPUT"
echo "$REF_TARGETS" >> "$GITHUB_OUTPUT"
echo "EOF" >> "$GITHUB_OUTPUT"

- name: Build all *-ref targets via d2x-buildtools
run: |
set -eu
while IFS= read -r tgt; do
[ -z "$tgt" ] && continue
echo "::group::build $tgt"
xmake d2x-buildtools --command=build --target="$tgt"
echo "::endgroup::"
done <<< "${{ steps.list_ref.outputs.targets }}"

- name: Run all *-ref targets via d2x-buildtools and assert no ❌
run: |
set -eu
fail=0
while IFS= read -r tgt; do
[ -z "$tgt" ] && continue
echo "::group::run $tgt"
output=$(xmake d2x-buildtools --command=run --target="$tgt" 2>&1)
echo "$output"
if echo "$output" | grep -qE '❌|Compilation/Running failed'; then
echo "::error::reference target $tgt produced a ❌ — exercise solution does not pass its own asserts"
fail=1
fi
if echo "$output" | grep -q 'Delete the D2X_WAIT to continue'; then
echo "::error::reference target $tgt still contains D2X_WAIT — remove it from the solution"
fail=1
fi
echo "::endgroup::"
done <<< "${{ steps.list_ref.outputs.targets }}"
exit $fail

- name: Verify dslings ↔ solutions filename parity
run: |
set -eu
# Every dslings/{cpp,hpp} file should have a matching solutions/ counterpart
missing=0
while IFS= read -r f; do
rel="${f#dslings/}"
# Skip the en/ mirror — solutions are language-neutral
case "$rel" in
en/*) continue ;;
esac
if [ ! -f "solutions/$rel" ]; then
echo "::warning::missing solutions/$rel (paired with dslings/$rel)"
missing=$((missing+1))
fi
done < <(find dslings -name '*.cpp' -not -path 'dslings/en/*')
if [ "$missing" -gt 0 ]; then
echo "::warning::$missing dslings exercises do not yet have a reference solution. This is informational during the bring-up phase; tighten to error once cpp11 is fully covered."
fi
33 changes: 33 additions & 0 deletions solutions/cpp11/00-auto-and-decltype-0.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// d2mcpp: https://github.com/mcpp-community/d2mcpp
// license: Apache-2.0
// reference solution for: dslings/cpp11/00-auto-and-decltype-0.cpp
//
// 用途: 仅给 CI 与维护者参考使用,不是教程入口。
// 教程练习入口: dslings/cpp11/00-auto-and-decltype-0.cpp
//

#include <d2x/cpp/common.hpp>

int main() {

// 0. 声明定义
int a = 1;
auto a1 = a; // a1: int
int b = 2;
auto b1 = b; // b1: int

decltype(b) b2 = b; // b2: int
decltype(a) a2 = a; // a2: int

char c = 'c';
auto c1 = c; // c1: char
decltype(c) c2 = c; // c2: char
(void)c1; (void)c2;

d2x_assert_eq(a, a1);
d2x_assert_eq(a1, a2);
d2x_assert_eq(b, b1);
d2x_assert_eq(b1, b2);

return 0;
}
33 changes: 33 additions & 0 deletions solutions/cpp11/00-auto-and-decltype-1.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// d2mcpp: https://github.com/mcpp-community/d2mcpp
// license: Apache-2.0
// reference solution for: dslings/cpp11/00-auto-and-decltype-1.cpp
//
// 用途: 仅给 CI 与维护者参考使用,不是教程入口。
// 教程练习入口: dslings/cpp11/00-auto-and-decltype-1.cpp
//

#include <d2x/cpp/common.hpp>

int main() {

// 1. 表达式
int a = 1;
auto a1 = a + 2;
auto a2 = a + 2 + 1.1; // double

int b = 2;
decltype(a + 0.1) b1 = a + 0.1; // double
decltype(a + b + 1.1) b2 = a + b + 1.1;
(void)a1; (void)b2;

char c = 'c';
auto c1 = 1 + c; // int
decltype(2 + 'a') c2 = 2 + 'a';

d2x_assert_eq(a2, a + 2 + 1.1);
d2x_assert_eq(b1, a + 0.1);
d2x_assert_eq(c1, 1 + c);
d2x_assert_eq(c2, 2 + 'a');

return 0;
}
48 changes: 48 additions & 0 deletions solutions/cpp11/00-auto-and-decltype-2.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// d2mcpp: https://github.com/mcpp-community/d2mcpp
// license: Apache-2.0
// reference solution for: dslings/cpp11/00-auto-and-decltype-2.cpp
//
// 用途: 仅给 CI 与维护者参考使用,不是教程入口。
// 教程练习入口: dslings/cpp11/00-auto-and-decltype-2.cpp
//

#include <d2x/cpp/common.hpp>

#include <iostream>
#include <vector>
#include <functional>

int add_func(int a, int b) {
return a + b;
}

int main() {

// 2. 复杂类型

std::vector<int> v = {1, 2, 3};

std::vector<int>::iterator v1 = v.begin();
for (; v1 != v.end(); ++v1) {
std::cout << *v1 << " ";
}
std::cout << std::endl;

auto v2 = v.begin();
for (; v2 != v.end(); ++v2) {
std::cout << *v2 << " ";
}
std::cout << std::endl;

auto minus_func = [](int a, int b) { return a - b; };

std::vector<std::function<int(int, int)>> funcVec = {
add_func,
minus_func
};

d2x_assert_eq(funcVec[0](1, 2), 3);
d2x_assert_eq(funcVec[1](1, 2), -1);

return 0;
}
32 changes: 32 additions & 0 deletions solutions/cpp11/00-auto-and-decltype-3.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// d2mcpp: https://github.com/mcpp-community/d2mcpp
// license: Apache-2.0
// reference solution for: dslings/cpp11/00-auto-and-decltype-3.cpp
//
// 用途: 仅给 CI 与维护者参考使用,不是教程入口。
// 教程练习入口: dslings/cpp11/00-auto-and-decltype-3.cpp
//

#include <d2x/cpp/common.hpp>

#include <iostream>
#include <vector>

// 3. 函数返回值类型

auto add_func(int a, double b) -> decltype(a + b) {
return a + b;
}

template<typename T1, typename T2>
auto minus_func(T1 a, T2 b) -> decltype(a - b) {
return a - b;
}

int main() {

d2x_assert_eq(minus_func(1, 2), -1);
d2x_assert_eq(minus_func(2, 1), 1);
d2x_assert_eq(minus_func(1, 2.1), -1.1);

return 0;
}
46 changes: 46 additions & 0 deletions solutions/cpp11/00-auto-and-decltype-4.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// d2mcpp: https://github.com/mcpp-community/d2mcpp
// license: Apache-2.0
// reference solution for: dslings/cpp11/00-auto-and-decltype-4.cpp
//
// 用途: 仅给 CI 与维护者参考使用,不是教程入口。
// 教程练习入口: dslings/cpp11/00-auto-and-decltype-4.cpp
//

#include <d2x/cpp/common.hpp>

#include <type_traits>


// 4. 类/结构体成员类型推导

struct Object {
const int a;
double b;
Object() : a(1), b(2.0) { }
};

int main() {
const Object obj;

bool type_check = false;

// obj的类型推导 和 (obj) 的类型推导
type_check = std::is_same<decltype(obj), const Object>::value;
d2x_assert(type_check); type_check = false; // dont change this line
type_check = std::is_same<decltype((obj)), const Object &>::value;
d2x_assert(type_check); type_check = false; // dont change this line

// obj.a的类型推导 和 (obj.a) 的类型推导
type_check = std::is_same<decltype(obj.a), const int>::value;
d2x_assert(type_check); type_check = false; // dont change this line
type_check = std::is_same<decltype((obj.a)), const int &>::value;
d2x_assert(type_check); type_check = false; // dont change this line

// obj.b的类型推导 和 (obj.b) 的类型推导
type_check = std::is_same<decltype(obj.b), double>::value;
d2x_assert(type_check); type_check = false; // dont change this line
type_check = std::is_same<decltype((obj.b)), const double &>::value;
d2x_assert(type_check); type_check = false; // dont change this line

return 0;
}
32 changes: 32 additions & 0 deletions solutions/cpp11/01-default-and-delete-0.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// d2mcpp: https://github.com/mcpp-community/d2mcpp
// license: Apache-2.0
// reference solution for: dslings/cpp11/01-default-and-delete-0.cpp
//
// 用途: 仅给 CI 与维护者参考使用,不是教程入口。
// 教程练习入口: dslings/cpp11/01-default-and-delete-0.cpp
//

#include <d2x/cpp/common.hpp>

#include <iostream>

// default和delete显式控制 -> 编译器默认构造函数的生成行为
struct A { };
struct B {
B() = default;
B(int x) { std::cout << "B(int x)" << std::endl; (void)x; }
};
struct C {
C() = default;
C(int x) { std::cout << "C(int x): " << x << std::endl; }
};

int main() { // 不要直接修改main函数中的代码

A a;
B b;
C c(1);
(void)a; (void)b; (void)c;

return 0;
}
36 changes: 36 additions & 0 deletions solutions/cpp11/01-default-and-delete-1.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// d2mcpp: https://github.com/mcpp-community/d2mcpp
// license: Apache-2.0
// reference solution for: dslings/cpp11/01-default-and-delete-1.cpp
//
// 用途: 仅给 CI 与维护者参考使用,不是教程入口。
// 教程练习入口: dslings/cpp11/01-default-and-delete-1.cpp
//

#include <d2x/cpp/common.hpp>

#include <iostream>

// 实现std::unique_ptr不可以拷贝, 但可以移动的属性
struct UniquePtr {
void *dataPtr;
UniquePtr() = default;

UniquePtr(const UniquePtr&) = delete;
UniquePtr& operator=(const UniquePtr&) = delete;

UniquePtr(UniquePtr&&) = default;
UniquePtr& operator=(UniquePtr&&) = default;
};

int main() { // 不要直接修改main函数中的代码

UniquePtr a;

d2x_assert(std::is_copy_constructible<UniquePtr>::value == false);
d2x_assert(std::is_copy_assignable<UniquePtr>::value == false);
d2x_assert(std::is_move_constructible<UniquePtr>::value == true);
d2x_assert(std::is_move_assignable<UniquePtr>::value == true);
(void)a;

return 0;
}
Loading
Loading