Skip to content

Commit 6f2d537

Browse files
committed
First commit.
1 parent 27f148d commit 6f2d537

16 files changed

+1164
-1
lines changed

Makefile

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Compiler, tools and options
2+
3+
CC = gcc
4+
CX = g++
5+
LB = ar -csr
6+
DEFINES =
7+
CFLAGS = -pipe -frtti -Wall -Wextra -fexceptions -march=nocona -c -std=c++1y
8+
LFLAGS = -Wl,-s
9+
INCPATH = -I"./"
10+
11+
CFLAGS += -O2 -DNDEBUG
12+
Configuration = release
13+
14+
# Output directory
15+
16+
OUT = ./build/bin/$(Configuration)/$(CC)
17+
TMP = ./build/tmp/$(Configuration)/$(CC)
18+
19+
# Build rules
20+
21+
.PHONY: all clean out tmp
22+
23+
all: $(TMP)/match_gcc/main.o match_gcc
24+
25+
clean:
26+
-rm -fr ./build
27+
28+
out:
29+
-mkdir -p $(OUT)
30+
31+
tmp:
32+
-mkdir -p $(TMP)
33+
34+
# Compile
35+
36+
$(TMP)/match_gcc/main.o: ./main.cpp | tmp
37+
$(CX) -o $(TMP)/main.o $(CFLAGS) $(INCPATH) ./main.cpp
38+
39+
match_gcc: $(TMP)/main.o | out
40+
$(CX) -o $(OUT)/match $(LFLAGS) $(TMP)/main.o
41+

README.md

+102-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,102 @@
1-
# cpp-match-case
1+
# match-case
2+
ML-style pattern matching in C++.
3+
The code has been compiled in MSVC-2005-CTP & g++-4.9.1(-std=c++1y).
4+
5+
For using it, you only need to include match.hpp.
6+
Some examples:
7+
8+
/*
9+
* For matching more than one condition at the same time.
10+
*/
11+
int a = 3, b = 321;
12+
Match(a, b)
13+
{
14+
Case(3, 123) std::cout << 1 << std::endl;
15+
Case(1, 2) std::cout << 2 << std::endl;
16+
Case(3, 321) std::cout << 3 << std::endl;
17+
Otherwise() std::cout << "Otherwise..." << std::endl;
18+
}
19+
EndMatch
20+
21+
Match()
22+
{
23+
Case(a == 3, b == 123) std::cout << 1 << std::endl;
24+
Case(c == TEST_COUNT * 3) std::cout << 2 << std::endl;
25+
Otherwise() std::cout << "Otherwise..." << std::endl;
26+
}
27+
EndMatch
28+
29+
/*
30+
* For matching a special type. If the target of matching is a polymorphic type,
31+
* the matching-case will try to cast the target, and match the right subclass.
32+
*/
33+
class Foo
34+
{
35+
public:
36+
virtual ~Foo(void) {}
37+
};
38+
39+
template <int N>
40+
class Bar : public Foo
41+
{
42+
};
43+
44+
Foo* foo = new Bar<2>;
45+
Match(foo, a)
46+
{
47+
Case(Type(Bar<1>), Type(short)) std::cout << 1 << std::endl;
48+
Case(Type(Bar<2>)) std::cout << 2 << std::endl;
49+
Case(Type(Bar<3>), b) std::cout << 3 << std::endl;
50+
Otherwise() std::cout << "Otherwise..." << std::endl;
51+
}
52+
EndMatch
53+
54+
/*
55+
* Regular expression
56+
*/
57+
std::string str = "\\w+(\\.\\w+)*@\\w+(\\.\\w+)+";
58+
59+
{
60+
Case("Hello World") std::cout << 1 << std::endl;
61+
Case("I Love You") std::cout << 2 << std::endl;
62+
Case(Regex(str)) std::cout << 3 << std::endl;
63+
Otherwise() std::cout << "Otherwise..." << std::endl;
64+
}
65+
EndMatch
66+
67+
/*
68+
* Automatically identify the closures, and using it as the matching pattern.
69+
*/
70+
Match(5)
71+
{
72+
Case([](int x){ return (x & 1); })
73+
std::cout << "odd" << std::endl;
74+
Otherwise()
75+
std::cout << "even" << std::endl;
76+
}
77+
EndMatch
78+
79+
/*
80+
* You can define your own filter for some special case.
81+
* The custom filter will work when the case pattern accords with it.
82+
* If the pattern matches more than one filter, you would get an ambiguity compile error.
83+
*/
84+
namespace match
85+
{
86+
template <typename T>
87+
inline auto filter(T&& arg)
88+
-> typename std::enable_if<std::is_same<typename std::decay<T>::type, const char*>::value, T&&>::type
89+
{
90+
std::cout << "My filter... " << arg << std::endl;
91+
return std::forward<T>(arg);
92+
}
93+
}
94+
#include "match.hpp"
95+
96+
Yuriy Solodkyy, Gabriel Dos Reis, Bjarne Stroustrup had written a paper:
97+
http://www.stroustrup.com/OpenPatternMatching.pdf
98+
And we can find their codes here:
99+
http://parasol.tamu.edu/mach7/
100+
Their library is very powerful and big, maybe a little complicated.
101+
Compared with their library, mine is very small and simple. I wrote only 170 lines of code for mine library.
102+
If you just want to use a pattern matching in C++ quickly, and don't like to read doc & study usage, maybe you could try my library.

capo/preprocessor.hpp

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
The Capo Library
3+
Code covered by the MIT License
4+
5+
Author: mutouyun (http://darkc.at)
6+
*/
7+
8+
#pragma once
9+
10+
//////////////////////////////////////////////////////////////////////////
11+
12+
#include "capo/preprocessor/pp_macros.hpp"
13+
#include "capo/preprocessor/pp_count.hpp"
14+
#include "capo/preprocessor/pp_arg.hpp"
15+
#include "capo/preprocessor/pp_repeat.hpp"
16+
#include "capo/preprocessor/pp_nest.hpp"
17+
#include "capo/preprocessor/pp_mult.hpp"
18+
#include "capo/preprocessor/pp_functions.hpp"
19+
20+
//////////////////////////////////////////////////////////////////////////

capo/preprocessor/pp_arg.hpp

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*
2+
The Capo Library
3+
Code covered by the MIT License
4+
5+
Author: mutouyun (http://darkc.at)
6+
*/
7+
8+
#pragma once
9+
10+
#include "capo/preprocessor/pp_macros.hpp"
11+
12+
//////////////////////////////////////////////////////////////////////////
13+
14+
/*
15+
CAPO_PP_B_2_(a, b, c, d, e)
16+
-->
17+
c, d, e
18+
*/
19+
20+
#define CAPO_PP_B_H_(a, ...) __VA_ARGS__
21+
22+
#define CAPO_PP_B_0_(...) CAPO_PP_VA_(__VA_ARGS__)
23+
#define CAPO_PP_B_1_(...) CAPO_PP_VA_(CAPO_PP_B_H_(__VA_ARGS__))
24+
#define CAPO_PP_B_2_(...) CAPO_PP_B_1_(CAPO_PP_B_1_(__VA_ARGS__))
25+
#define CAPO_PP_B_3_(...) CAPO_PP_B_1_(CAPO_PP_B_2_(__VA_ARGS__))
26+
#define CAPO_PP_B_4_(...) CAPO_PP_B_1_(CAPO_PP_B_3_(__VA_ARGS__))
27+
#define CAPO_PP_B_5_(...) CAPO_PP_B_1_(CAPO_PP_B_4_(__VA_ARGS__))
28+
#define CAPO_PP_B_6_(...) CAPO_PP_B_1_(CAPO_PP_B_5_(__VA_ARGS__))
29+
#define CAPO_PP_B_7_(...) CAPO_PP_B_1_(CAPO_PP_B_6_(__VA_ARGS__))
30+
#define CAPO_PP_B_8_(...) CAPO_PP_B_1_(CAPO_PP_B_7_(__VA_ARGS__))
31+
#define CAPO_PP_B_9_(...) CAPO_PP_B_1_(CAPO_PP_B_8_(__VA_ARGS__))
32+
33+
#define CAPO_PP_B_10_(...) CAPO_PP_B_1_(CAPO_PP_B_9_(__VA_ARGS__))
34+
#define CAPO_PP_B_11_(...) CAPO_PP_B_1_(CAPO_PP_B_10_(__VA_ARGS__))
35+
#define CAPO_PP_B_12_(...) CAPO_PP_B_1_(CAPO_PP_B_11_(__VA_ARGS__))
36+
#define CAPO_PP_B_13_(...) CAPO_PP_B_1_(CAPO_PP_B_12_(__VA_ARGS__))
37+
#define CAPO_PP_B_14_(...) CAPO_PP_B_1_(CAPO_PP_B_13_(__VA_ARGS__))
38+
#define CAPO_PP_B_15_(...) CAPO_PP_B_1_(CAPO_PP_B_14_(__VA_ARGS__))
39+
#define CAPO_PP_B_16_(...) CAPO_PP_B_1_(CAPO_PP_B_15_(__VA_ARGS__))
40+
#define CAPO_PP_B_17_(...) CAPO_PP_B_1_(CAPO_PP_B_16_(__VA_ARGS__))
41+
#define CAPO_PP_B_18_(...) CAPO_PP_B_1_(CAPO_PP_B_17_(__VA_ARGS__))
42+
#define CAPO_PP_B_19_(...) CAPO_PP_B_1_(CAPO_PP_B_18_(__VA_ARGS__))
43+
44+
#define CAPO_PP_B_20_(...) CAPO_PP_B_1_(CAPO_PP_B_19_(__VA_ARGS__))
45+
46+
#define CAPO_PP_B_P_(F, ...) CAPO_PP_VA_(F(__VA_ARGS__))
47+
#define CAPO_PP_B_(N, ...) CAPO_PP_B_P_(CAPO_PP_JOIN_(CAPO_PP_B_, CAPO_PP_JOIN_(N, _)), __VA_ARGS__)
48+
49+
//////////////////////////////////////////////////////////////////////////
50+
51+
/*
52+
CAPO_PP_A_3_(a, b, c, d, e)
53+
-->
54+
c
55+
*/
56+
57+
#define CAPO_PP_A_H_(a, ...) a
58+
59+
#define CAPO_PP_A_0_(...)
60+
#define CAPO_PP_A_1_(...) CAPO_PP_VA_(CAPO_PP_A_H_(__VA_ARGS__))
61+
#define CAPO_PP_A_2_(...) CAPO_PP_A_1_(CAPO_PP_B_1_(__VA_ARGS__))
62+
#define CAPO_PP_A_3_(...) CAPO_PP_A_1_(CAPO_PP_B_2_(__VA_ARGS__))
63+
#define CAPO_PP_A_4_(...) CAPO_PP_A_1_(CAPO_PP_B_3_(__VA_ARGS__))
64+
#define CAPO_PP_A_5_(...) CAPO_PP_A_1_(CAPO_PP_B_4_(__VA_ARGS__))
65+
#define CAPO_PP_A_6_(...) CAPO_PP_A_1_(CAPO_PP_B_5_(__VA_ARGS__))
66+
#define CAPO_PP_A_7_(...) CAPO_PP_A_1_(CAPO_PP_B_6_(__VA_ARGS__))
67+
#define CAPO_PP_A_8_(...) CAPO_PP_A_1_(CAPO_PP_B_7_(__VA_ARGS__))
68+
#define CAPO_PP_A_9_(...) CAPO_PP_A_1_(CAPO_PP_B_8_(__VA_ARGS__))
69+
70+
#define CAPO_PP_A_10_(...) CAPO_PP_A_1_(CAPO_PP_B_9_(__VA_ARGS__))
71+
#define CAPO_PP_A_11_(...) CAPO_PP_A_1_(CAPO_PP_B_10_(__VA_ARGS__))
72+
#define CAPO_PP_A_12_(...) CAPO_PP_A_1_(CAPO_PP_B_11_(__VA_ARGS__))
73+
#define CAPO_PP_A_13_(...) CAPO_PP_A_1_(CAPO_PP_B_12_(__VA_ARGS__))
74+
#define CAPO_PP_A_14_(...) CAPO_PP_A_1_(CAPO_PP_B_13_(__VA_ARGS__))
75+
#define CAPO_PP_A_15_(...) CAPO_PP_A_1_(CAPO_PP_B_14_(__VA_ARGS__))
76+
#define CAPO_PP_A_16_(...) CAPO_PP_A_1_(CAPO_PP_B_15_(__VA_ARGS__))
77+
#define CAPO_PP_A_17_(...) CAPO_PP_A_1_(CAPO_PP_B_16_(__VA_ARGS__))
78+
#define CAPO_PP_A_18_(...) CAPO_PP_A_1_(CAPO_PP_B_17_(__VA_ARGS__))
79+
#define CAPO_PP_A_19_(...) CAPO_PP_A_1_(CAPO_PP_B_18_(__VA_ARGS__))
80+
81+
#define CAPO_PP_A_20_(...) CAPO_PP_A_1_(CAPO_PP_B_19_(__VA_ARGS__))
82+
83+
#define CAPO_PP_A_P_(F, ...) CAPO_PP_VA_(F(__VA_ARGS__))
84+
#define CAPO_PP_A_(N, ...) CAPO_PP_A_P_(CAPO_PP_JOIN_(CAPO_PP_A_, CAPO_PP_JOIN_(N, _)), __VA_ARGS__)

capo/preprocessor/pp_count.hpp

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
The Capo Library
3+
Code covered by the MIT License
4+
5+
Author: mutouyun (http://darkc.at)
6+
*/
7+
8+
#pragma once
9+
10+
#include "capo/preprocessor/pp_macros.hpp"
11+
12+
//////////////////////////////////////////////////////////////////////////
13+
14+
#define CAPO_PP_MAX_ 20
15+
16+
#define CAPO_PP_FILTER__( _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \
17+
_11, _12, _13, _14, _15, _16, _17, _18, _19, _20, \
18+
_N, ...) _N
19+
20+
#define CAPO_PP_NUMBER__() 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, \
21+
10, 9, 8, 7, 6, 5, 4, 3, 2, 1
22+
23+
/*
24+
Get count of args from __VA_ARGS__
25+
26+
CAPO_PP_COUNT_(a, b, c, d)
27+
-->
28+
4
29+
*/
30+
31+
#define CAPO_PP_HELPER_(...) CAPO_PP_VA_(CAPO_PP_FILTER__(__VA_ARGS__))
32+
#define CAPO_PP_COUNT_(...) CAPO_PP_HELPER_(__VA_ARGS__, CAPO_PP_NUMBER__())

0 commit comments

Comments
 (0)