diff --git a/README.md b/README.md index 41478dd..c159a08 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,31 @@ # Better Enums -Generator-free reflective C++11 enum library with clean syntax. For example: +Reflective compile-time C++11 enum library with clean syntax. For example: ENUM(Channel, int, Red = 1, Green, Blue); defines a type `Channel`. You can then do natural things like: - Channel channel = Channel::Green; +```cpp +Channel channel = Channel::Green; - channel.to_string(); // Results in the string "Green" - channel.to_integral(); // Results in the integer 2 +channel.to_string(); // Results in the string "Green" +channel.to_integral(); // Results in the int 2 - Channel::_from_string("Red"); // Results in Channel::Red - Channel::_from_int(3) // Results in Channel::Blue +Channel::_from_string("Red"); // Results in Channel::Red +Channel::_from_integral(3); // Results in Channel::Blue - for (Channel channel : Channel::_values) { - // Iterate over all channels - } +constexpr auto channel = Channel::_from_integral(3); + // Do it at compile time +constexpr auto channel = Channel::_max; + // Channel::Blue -...and more. See the +for (Channel channel : Channel::_values) { + // Iterate over all channels +} +``` + +...and more. See the [project page](http://aantron.github.io/better-enums) and [examples](https://github.com/aantron/better-enums/tree/master/example) for a tutorial. diff --git a/doc/api.html b/doc/api.html new file mode 100644 index 0000000..f1d08cd --- /dev/null +++ b/doc/api.html @@ -0,0 +1,939 @@ + + + + + + + +Better Enums - Reference + + + + + + + + + + + + +
+ + +

+ + Better Enums 0.8.0 + +

+
+ +
+ +
+ +

+ The best way to get started with Better Enums is to read the + project page and browse + the commented + + examples. This page gives reference documentation. +

+ +

The following declaration

+ +
#include <enum.h>
+ENUM(Enum, underlying_type, A, B, C);
+ +

+ generates a new type Enum. It is notionally similar to the type + created by this declaration: +

+ +
enum class Enum : underlying_type {A, B, C};
+ +

+ that is, it is an enumerated type with constants Enum::A, + Enum::B, and Enum::C, and is represented in memory by an + integer of type underlying_type. Just like with a built-in + enum class, it is possible to specify numeric values and aliases + for constants: +

+ +
ENUM(Enum, underlying_type, A = 1, B, C, D = A);
+ +

+ Constant values are assigned by the compiler by exactly the same rules as + for a built-in enum, so in the above example, Enum::A == 1, + Enum::B == 2, Enum::C == 3, and Enum::D == 1. +

+ +
+ +
+ + +

Member index

+ + + + + + + + + + + + + + + +
+ + + +
+ +
+ + +

+ Internal enumerated type + index +

+ + +

typename Enum::_Enumerated

+ +

+ The declared type Enum is built around an internal + C++ enumeration. Notionally, +

+ +
ENUM(Enum, int, A, B, C);
+ +

produces

+ +
class Enum {
+    ...
+  public:
+    enum _Enumerated : int {A, B, C};
+    ...
+};
+ +

+ _Enumerated is simply the name of the internal enumeration. The + user should not use this type name directly, but it is referred to in the + rest of the documentation. The name is exposed because a literal + Enum::A is not a value of type Enum, but a value of type + Enum::_Enumerated, which is convertible to Enum, in most + cases implicitly. +

+ +

+ Note that _Enumerated is not a + C++11 + enum class. +

+ + +

+ implicit constructor constexpr Enum(_Enumerated) +

+ +

+ A converting constructor for promoting values of type _Enumerated + to values of type Enum. As mentioned above, this typically happens + automatically when you write a literal constant such as Enum::A in + a context where a value of type Enum is expected. For example: +

+ +
void do_something(Enum value) { ... }
+
+do_something(Enum::A);  // converted silently
+ + +

+ global unary constexpr operator +(_Enumerated) +

+ +

+ For use when the compiler does not choose the implicit constructor above. + For example: +

+ +
(Enum::A).to_string()
+ +

+ This expression does not compile because Enum::A is not an object, + and the compiler does not promote it. The promotion can be forced: +

+ +
(+Enum::A).to_string()
+ +

+ This is easier to maintain than writing out a call to the converting + constructor: +

+ +
((Enum)Enum::A).to_string()
+ + +

+ casting constexpr operator _Enumerated() const +

+ +

+ Enables implicit conversion of Enum values down to + _Enumerated. The only purpose of this is to make Enum + values directly usable in switch statements for compiler-supported + case checking: +

+ +
switch(enum_value) {
+    case Enum::A: ...; break;
+    case Enum::B: ...; break;
+    case Enum::C: ...; break;
+}
+ +

+ It is, unfortunately, a hole in the type safety of Enum, since it + allows implicit conversions to integral types (Enum to + _Enumerated, then _Enumerated to an integer). The user + should not rely on such conversions. They will probably be eliminated in the + future, perhaps by replacing this conversion with a conversion to an + enum class. +

+ +
+ + + +
+ + +

+ Underlying integral type + index +

+ + +

typename Enum::_Integral

+ +

+ An alias for the underlying type that Enum was declared with. For + example, if the declaration is +

+ +
ENUM(Enum, uint32_t, A, B, C);
+ +

+ Then Enum::_Integral is the same as uint32_t. +

+ + +

static constexpr Enum _from_integral(_Integral)

+ +

+ Checked cast from a numeric value to an enum value. The function checks that + there is an enum constant with the given value. If not, it throws + std::runtime_error. The check takes time linear in the + number of constants in Enum. +

+ + +

+ static constexpr Enum _from_integral_unchecked(_Integral) +

+ +

+ Unchecked cast from a numeric value to an enum value. The function assumes + that there is an enum constant with the given value. The user has to ensure + that this assumption holds. If not, the behavior of subsequent operations + on the returned enum value is undefined. +

+ + +

+ member constexpr + _Integral enum_value.to_integral() const +

+ +

+ Returns the numeric representation of an enum value. +

+ + +

static constexpr bool _is_valid(_Integral)

+ +

+ Checks that the given numeric value represents one of the constants in + Enum, as in _from_integral. Complexity is linear + in the number of constants. +

+ +

invariant sizeof(Enum) == sizeof(Enum::_Integral)

+ +

invariant alignof(Enum) == alignof(Enum::_Integral)

+ +
+ + + +
+ + +

+ String conversions + index +

+ + +

static constexpr Enum _from_string(const char*)

+ +

+ Returns the enum constant given by the string. For example: +

+ +
Enum::_from_string("A") == Enum::A
+ +

+ Complexity is linear in the number of constants multiplied by the + length of the longest constant name. If the string does not name a constant, + throws std::runtime_error. +

+ + +

static constexpr Enum _from_string_nocase(const char*)

+ +

+ The same as above, but lookup is case-insensitive. +

+ + +

+ member const char* enum_value.to_string() + const +

+ +

+ Returns the string representation of enum value on which the method is + called. If multiple constants have the same numeric value, the string + returned can be the representation any of the constants. Note that this + method is not constexpr. Complexity is linear in + the number of constants. If the string does not name a constant, + throws std::runtime_error. +

+ + +

static constexpr const char *_name

+ +

+ The name of the type, i.e., for +

+ +
ENUM(Enum, int, A, B, C);
+ +

+ Enum::_name == "Enum" +

+ + +

static constexpr bool _is_valid(const char*)

+ +

+ Checks that the given string is the name of one of the constants in + Enum, as in _from_string, with the same complexity. +

+ + +

static constexpr bool _is_valid_nocase(const char*)

+ +

+ The same as above, but corresponding to _from_string_nocase. +

+ +
+ + + +
+ + +

+ Iteration + index +

+ + +

static constexpr _ValueIterable values

+ +

+ An iterable container with all the defined constant values, in declaration + order. Suitable for use with range-based for loops: +

+ +
for (Enum value : Enum::_values) {
+    // Will iterate over Enum::A, Enum::B, Enum::C
+}
+ +

class _ValueIterable::iterator

+ +

+ An iterator over defined constant values with a constexpr + dereference operator. Can be created explicitly by the constexpr + expressions +

+ +
Enum::_values::begin()
+Enum::_values::end()
+ + +

static constexpr _NameIterable names

+ +

+ An iterable container with the names of the defined constant values, in + declaration order. Suitable for use with range-based for loops: +

+ +
for (const char *name : Enum::_names) {
+    // Will iterate over "A", "B", "C"
+}
+ +

class _NameIterable::iterator

+ +

+ An iterator over defined constant names with a dereference operator that is + not constexpr. Can be created explicitly by the + constexpr expressions +

+ +
Enum::_names::begin()
+Enum::_names::end()
+ +
+ + + +
+ + +

+ Range properties + index +

+ + +

static constexpr _Enumerated _first

+ +

+ The first defined constant. For example, in +

+ +
ENUM(Enum, int, A = 1, B = 5, C = 0);
+ +

Enum::_first == Enum::A

+ + +

static constexpr _Enumerated _last

+ +

+ The last defined constant, i.e. Enum::C in the above example. +

+ + +

static constexpr _Enumerated _min

+ +

+ The defined constant with the smallest numeric value, i.e. Enum::C + in the above example. +

+ + +

static constexpr _Enumerated _max

+ +

+ The defined constant with the greatest numeric value, i.e. Enum::B + in the above example. +

+ + +

static constexpr size_t _size

+ +

+ The number of constants defined, i.e. 3 in the above example. +

+ + +

static constexpr _Integral _span

+ +

+ The numeric span of the constants defined, i.e. _max - _min + 1, + which is 6 in the above example. +

+ +
+ + + +
+ + +

+ Comparisons + index +

+ +

+ member constexpr bool operator ==(const Enum&) + const +

+ +

+ member constexpr bool operator ==(_Enumerated) + const +

+ +

+ member constexpr bool operator !=(const Enum&) + const +

+ +

+ member constexpr bool operator !=(_Enumerated) + const +

+ +

+ member constexpr bool operator <(const Enum&) + const +

+ +

+ member constexpr bool operator <(_Enumerated) + const +

+ +

+ member constexpr bool operator <=(const Enum&) + const +

+ +

+ member constexpr bool operator <=(_Enumerated) + const +

+ +

+ member constexpr bool operator >(const Enum&) + const +

+ +

+ member constexpr bool operator >(_Enumerated) + const +

+ +

+ member constexpr bool operator >=(const Enum&) + const +

+ +

+ member constexpr bool operator >=(_Enumerated) + const +

+ +

+ These define an ordering on values of types Enum and + Enum::_Enumerated. The ordering is according to the values' + numeric representations. That means that two values that have been aliased + will compare equal. Direct comparisons with all other types are forbidden; + this is enforced by deleted comparison operators for all other types. +

+ +
+ + + +
+ + +

+ Additional type safety + index +

+ +

default constructor Enum() = delete

+ +

+ The default constructor is deleted to encourage initialization with valid + values only and to avoid undefined states. See + + example/6-traits.cc for an example of how to add an explicit notion of + default value. +

+ +

invariant no arithmetic

+ +

Arithmetic operators are explicitly deleted.

+ +

invariant no implicit conversion from integers

+ +
+ +
+ +
+ + + + + + + diff --git a/doc/index.html b/doc/index.html index 4e5fd9d..c54ab43 100644 --- a/doc/index.html +++ b/doc/index.html @@ -5,933 +5,254 @@ -Better Enums - No-Generator C++ Enums with String Conversions +Better Enums - Clean Reflective Enums for C++ - + - + -
- -

- - Better Enums 0.8.0 - -

+
+

Better Enums

+

Clean compile-time reflective enums for + C++11

+

C++98 support coming soon without the "compile-time" :)

-
+

+ Have you noticed the awkward situation with enums in + C++? Built-in enum class is missing + basic features, such as string conversion. There are several approaches to + address this, but most seem to involve unnatural syntax or code + repetition. See some here. +

-

- The best way to get started with Better Enums is to browse the commented - - examples, which form a kind of tutorial. This page gives reference - documentation. -

+

+ Better Enums gives you rich, reflective enums with the nicest syntax yet + seen.1 All you have to do is add two short, + simple header files to your project, and you are ready to go. +

-

The following declaration

+
#include <enum.h>
+ENUM(Channel, int, Red, Green, Blue);
-
#include <enum.h>
-ENUM(Enum, underlying_type, A, B, C);
+

+ This gives you an int-sized enum type with all sorts of + reflective capacity, including string conversions, value listing, + compile-time operations, static information about the range of declared + constants, and (last and probably least) the name "Channel" + itself. +

-

- generates a new type Enum. It is notionally similar to the type - created by this declaration: -

- -
enum class Enum : underlying_type {A, B, C};
- -

- that is, it is an enumerated type with constants Enum::A, - Enum::B, and Enum::C, and is represented in memory by an - integer of type underlying_type. Just like with a built-in - enum class, it is possible to specify numeric values and aliases - for constants: -

- -
ENUM(Enum, underlying_type, A = 1, B, C, D = A);
- -

- Constant values are assigned by the compiler by exactly the same rules as - for a built-in enum, so in the above example, Enum::A == 1, - Enum::B == 2, Enum::C == 3, and Enum::D == 1. -

+

+ The enum is easy to maintain. There is no duplication of value names, + no repetition of cumbersome macros, and no generator to run on every + build. The library is header-only and has no dependencies, so there aren't + any object files to link with. You can assign explicit values to constants + and alias them like with a normal enum. +

+

+ Better Enums is free, available under the BSD license. The + author is committed to further development and support, so please + contact me, open an issue on + GitHub, or ask a + question on Stack Overflow. +

+

Installation

- -

Member index

- - - - - - - - - - - - - - +

+ Download the + + latest release, then copy the files + enum.h and enum_preprocessor_map.h to your + project. That's it! Just make sure both files are in your include path and + you are compiling with gcc or + clang in + C++11 mode. +

+

+ msvc support is coming in a near-future version + with some enum features disabled. This is because + msvc's support for constexpr is + lagging. The same patch will probably make it possible to use Better Enums + with C++98. +

- - -
-
+

Tutorial

- -

- Internal enumerated type - index -

+

+ Create a file and put this code in it: +

- -

typename Enum::_Enumerated

+
#include <iostream>
+#include <enum.h>
 
-  

- The declared type Enum is built around an internal - C++ enumeration. Notionally, -

+ENUM(Channel, int, Red, Green, Blue); -
ENUM(Enum, int, A, B, C);
+int main() +{ + Channel my_channel = Channel::Green; + std::cout + << "Channel " + << my_channel.to_string() + << " has value " + << my_channel.to_integral() + << std::endl; -

produces

- -
class Enum {
-    ...
-  public:
-    enum _Enumerated : int {A, B, C};
-    ...
-};
- -

- _Enumerated is simply the name of the internal enumeration. The - user should not use this type name directly, but it is referred to in the - rest of the documentation. The name is exposed because a literal - Enum::A is not a value of type Enum, but a value of type - Enum::_Enumerated, which is convertible to Enum, in most - cases implicitly. -

- -

- Note that _Enumerated is not a - C++11 - enum class. -

- - -

- implicit constructor constexpr Enum(_Enumerated) -

- -

- A converting constructor for promoting values of type _Enumerated - to values of type Enum. As mentioned above, this typically happens - automatically when you write a literal constant such as Enum::A in - a context where a value of type Enum is expected. For example: -

- -
void do_something(Enum value) { ... }
-
-do_something(Enum::A);  // converted silently
- - -

- global unary constexpr operator +(_Enumerated) -

- -

- For use when the compiler does not choose the implicit constructor above. - For example: -

- -
(Enum::A).to_string()
- -

- This expression does not compile because Enum::A is not an object, - and the compiler does not promote it. The promotion can be forced: -

- -
(+Enum::A).to_string()
- -

- This is easier to maintain than writing out a call to the converting - constructor: -

- -
((Enum)Enum::A).to_string()
- - -

- casting constexpr operator _Enumerated() const -

- -

- Enables implicit conversion of Enum values down to - _Enumerated. The only purpose of this is to make Enum - values directly usable in switch statements for compiler-supported - case checking: -

- -
switch(enum_value) {
-    case Enum::A: ...; break;
-    case Enum::B: ...; break;
-    case Enum::C: ...; break;
+    return 0;
 }
-

- It is, unfortunately, a hole in the type safety of Enum, since it - allows implicit conversions to integral types (Enum to - _Enumerated, then _Enumerated to an integer). The user - should not rely on such conversions. They will probably be eliminated in the - future, perhaps by replacing this conversion with a conversion to an - enum class. -

+

+ Compile and run, and you should see the output + Channel Green has value 1. Congratulations! You have compiled + your first Better Enum. +

+
+ +

+ Values are assigned to Better Enums just like to regular + C++ enums. That means you can change the enum + above to something like this: +

+ +
ENUM(Channel, int, Red, Green = 5, Blue, Last = Blue);
+ +

+ and the result would be just as you'd expect: Red is 0, + Green is 5, Blue is 6, and Last is + also 6. +

+ +
+ +

+ There is no need for Last, however. Every Better Enum comes + with a built-in value called _last. So, if you have +

+ +
ENUM(Channel, int, Red, Green, Blue);
+ +

+ Then Channel::_last is Channel::Blue! In fact, + Channel also gets _first, _min, + _max, _span, and _size. These + built-in values have underscores so that you can define your own enums + without having to worry about naming problems: +

+ +
ENUM(Position, int, first, last, other);
+ +
+ +

+ You already saw how to convert an enum to a string or an integer. As you + might guess, it is also possible to go the other way: +

+ +

Channel   my_channel = Channel::_from_string("Blue");
+Channel   my_channel = Channel::_from_integral(2);
+ +

+ If your code tries to convert an invalid string or integer to a + Channel, it will get an std::runtime_error + exception. +

+ +
+ +

+ You can iterate over all the declared values of an enum: +

+ +
for(Channel channel : Channel::_values)
+    std::cout << channel.to_string() << std::endl;
+ +

+ and directly over their names with Channel::_names. +

+ +
+ +

+ Finally, most of the above is declared constexpr and can be + run at compile time. This means you can do all sorts of parsing and + processing at the same time the rest of your code is being compiled, + improving runtime and startup performance! See some + examples + and another + example. +

- -
+

Where to go from here

- -

- Underlying integral type - index -

- - -

typename Enum::_Integral

- -

- An alias for the underlying type that Enum was declared with. For - example, if the declaration is -

- -
ENUM(Enum, uint32_t, A, B, C);
- -

- Then Enum::_Integral is the same as uint32_t. -

- - -

static constexpr Enum _from_integral(_Integral)

- -

- Checked cast from a numeric value to an enum value. The function checks that - there is an enum constant with the given value. If not, it throws - std::runtime_error. The check takes time linear in the - number of constants in Enum. -

- - -

- static constexpr Enum _from_integral_unchecked(_Integral) -

- -

- Unchecked cast from a numeric value to an enum value. The function assumes - that there is an enum constant with the given value. The user has to ensure - that this assumption holds. If not, the behavior of subsequent operations - on the returned enum value is undefined. -

- - -

- member constexpr - _Integral enum_value.to_integral() const -

- -

- Returns the numeric representation of an enum value. -

- - -

static constexpr bool _is_valid(_Integral)

- -

- Checks that the given numeric value represents one of the constants in - Enum, as in _from_integral. Complexity is linear - in the number of constants. -

- -

invariant sizeof(Enum) == sizeof(Enum::_Integral)

- -

invariant alignof(Enum) == alignof(Enum::_Integral)

- +
- - - -
- - -

- String conversions - index -

- - -

static constexpr Enum _from_string(const char*)

- -

- Returns the enum constant given by the string. For example: -

- -
Enum::_from_string("A") == Enum::A
- -

- Complexity is linear in the number of constants multiplied by the - length of the longest constant name. If the string does not name a constant, - throws std::runtime_error. -

- - -

static constexpr Enum _from_string_nocase(const char*)

- -

- The same as above, but lookup is case-insensitive. -

- - -

- member const char* enum_value.to_string() - const -

- -

- Returns the string representation of enum value on which the method is - called. If multiple constants have the same numeric value, the string - returned can be the representation any of the constants. Note that this - method is not constexpr. Complexity is linear in - the number of constants. If the string does not name a constant, - throws std::runtime_error. -

- - -

static constexpr const char *_name

- -

- The name of the type, i.e., for -

- -
ENUM(Enum, int, A, B, C);
- -

- Enum::_name == "Enum" -

- - -

static constexpr bool _is_valid(const char*)

- -

- Checks that the given string is the name of one of the constants in - Enum, as in _from_string, with the same complexity. -

- - -

static constexpr bool _is_valid_nocase(const char*)

- -

- The same as above, but corresponding to _from_string_nocase. -

- -
- - - -
- - -

- Iteration - index -

- - -

static constexpr _ValueIterable values

- -

- An iterable container with all the defined constant values, in declaration - order. Suitable for use with range-based for loops: -

- -
for (Enum value : Enum::_values) {
-    // Will iterate over Enum::A, Enum::B, Enum::C
-}
- -

class _ValueIterable::iterator

- -

- An iterator over defined constant values with a constexpr - dereference operator. Can be created explicitly by the constexpr - expressions -

- -
Enum::_values::begin()
-Enum::_values::end()
- - -

static constexpr _NameIterable names

- -

- An iterable container with the names of the defined constant values, in - declaration order. Suitable for use with range-based for loops: -

- -
for (const char *name : Enum::_names) {
-    // Will iterate over "A", "B", "C"
-}
- -

class _NameIterable::iterator

- -

- An iterator over defined constant names with a dereference operator that is - not constexpr. Can be created explicitly by the - constexpr expressions -

- -
Enum::_names::begin()
-Enum::_names::end()
- -
- - - -
- - -

- Range properties - index -

- - -

static constexpr _Enumerated _first

- -

- The first defined constant. For example, in -

- -
ENUM(Enum, int, A = 1, B = 5, C = 0);
- -

Enum::_first == Enum::A

- - -

static constexpr _Enumerated _last

- -

- The last defined constant, i.e. Enum::C in the above example. -

- - -

static constexpr _Enumerated _min

- -

- The defined constant with the smallest numeric value, i.e. Enum::C - in the above example. -

- - -

static constexpr _Enumerated _max

- -

- The defined constant with the greatest numeric value, i.e. Enum::B - in the above example. -

- - -

static constexpr size_t _size

- -

- The number of constants defined, i.e. 3 in the above example. -

- - -

static constexpr _Integral _span

- -

- The numeric span of the constants defined, i.e. _max - _min + 1, - which is 6 in the above example. -

- -
- - - -
- - -

- Comparisons - index -

- -

- member constexpr bool operator ==(const Enum&) - const -

- -

- member constexpr bool operator ==(_Enumerated) - const -

- -

- member constexpr bool operator !=(const Enum&) - const -

- -

- member constexpr bool operator !=(_Enumerated) - const -

- -

- member constexpr bool operator <(const Enum&) - const -

- -

- member constexpr bool operator <(_Enumerated) - const -

- -

- member constexpr bool operator <=(const Enum&) - const -

- -

- member constexpr bool operator <=(_Enumerated) - const -

- -

- member constexpr bool operator >(const Enum&) - const -

- -

- member constexpr bool operator >(_Enumerated) - const -

- -

- member constexpr bool operator >=(const Enum&) - const -

- -

- member constexpr bool operator >=(_Enumerated) - const -

- -

- These define an ordering on values of types Enum and - Enum::_Enumerated. The ordering is according to the values' - numeric representations. That means that two values that have been aliased - will compare equal. Direct comparisons with all other types are forbidden; - this is enforced by deleted comparison operators for all other types. -

- -
- - - -
- - -

- Additional type safety - index -

- -

default constructor Enum() = delete

- -

- The default constructor is deleted to encourage initialization with valid - values only and to avoid undefined states. See - - example/6-traits.cc for an example of how to add an explicit notion of - default value. -

- -

invariant no arithmetic

- -

Arithmetic operators are explicitly deleted.

- -

invariant no implicit conversion from integers

- -
- -
-
- - diff --git a/doc/sitemap.xml b/doc/sitemap.xml new file mode 100644 index 0000000..a581a2a --- /dev/null +++ b/doc/sitemap.xml @@ -0,0 +1,12 @@ + + + + http://aantron.github.io/better-enums + daily + 1.0 + + + http://aantron.github.io/better-enums/api.html + daily + + diff --git a/doc/style.css b/doc/style.css new file mode 100644 index 0000000..388b13e --- /dev/null +++ b/doc/style.css @@ -0,0 +1,159 @@ +body { + margin: 0; + color: #555; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 18px; +} + +pre, code, samp { + font-family: + Consolas, "Liberation Mono", Menlo, "Courier New", Courier, monospace; + font-size: 16px; + + color: white; + text-shadow: 0 -1px grey; +} + +pre { + background-color: #8AAECB; + padding: 0.5em 20px; + border-radius: 5px; + overflow: scroll; +} + +code, samp { + background-color: #93B2CB; + padding: 1px 3px; + border-radius: 3px; +} + +nav > *, header > *, main > *, footer { + max-width: 760px; + padding-left: 230px; +} + +@media(max-width: 1240px) { + nav > *, header > *, main > *, footer { + padding-left: 150px; + } +} + +@media(max-width: 1060px) { + nav > *, header > *, main > *, footer { + padding-left: 100px; + padding-right: 100px; + } +} + +@media(max-width: 900px) { + nav > *, header > *, main > *, footer { + padding-left: 50px; + padding-right: 50px; + } +} + +@media(max-width: 680px) { + nav > *, header > *, main > *, footer { + padding-left: 20px; + padding-right: 20px; + } +} + +nav { + padding: 0.75em 0; + background-color: #222; + border-bottom: 1px solid #68a; + color: white; + font-size: 14px; + font-weight: 500; +} + +nav a { + margin-left: 2em; +} + +nav a.first { + margin-left: 0; + font-weight: 600; + font-size: 16px; +} + +header { + background-color: #4C6F8C; + background: linear-gradient(#4C6F8C, #769DBD); + color: white; + padding: 50px 0; + margin-bottom: 50px; +} + +h1 { + margin: 0; + font-size: 60px; + font-weight: 500; +} + +header > h2 { + margin: 0; + font-size: 24px; + font-weight: 300; + position: relative; + left: 3px; +} + +header > h3 { + margin: 0; + font-size: 14px; + font-weight: 300; + position: relative; + left: 4px; + opacity: 0.5; +} + +h2 { + font-weight: 500; + margin-top: 3em; +} + +hr { + border: none; + height: 20px; +} + +footer { + font-size: 16px; + margin-top: 150px; + margin-bottom: 20px; +} + +a { + background-color: red; + text-decoration: none; +} + +a:hover { + text-decoration: underline; +} + +a[href] { + background-color: #D07A6F; + color: white; + padding: 0 2px; + border-radius: 3px; +} + +nav a[href] { + color: inherit; + background-color: transparent; +} + +span.cpp, span.cc { + font-size: 90%; +} + +span.eleven { + font-size: 85%; +} + +span#note:target { + background-color: yellow; +}