Add py::exec() as a shortcut for py::eval<py::eval_statements>()
diff --git a/docs/advanced/pycpp/utilities.rst b/docs/advanced/pycpp/utilities.rst
index 442d0e9..e3d9c6c 100644
--- a/docs/advanced/pycpp/utilities.rst
+++ b/docs/advanced/pycpp/utilities.rst
@@ -24,16 +24,10 @@
 Evaluating Python expressions from strings and files
 ====================================================
 
-pybind11 provides the :func:`eval` and :func:`eval_file` functions to evaluate
+pybind11 provides the `eval`, `exec` and `eval_file` functions to evaluate
 Python expressions and statements. The following example illustrates how they
 can be used.
 
-Both functions accept a template parameter that describes how the argument
-should be interpreted. Possible choices include ``eval_expr`` (isolated
-expression), ``eval_single_statement`` (a single statement, return value is
-always ``none``), and ``eval_statements`` (sequence of statements, return value
-is always ``none``).
-
 .. code-block:: cpp
 
     // At beginning of file
@@ -48,7 +42,7 @@
     int result = py::eval("my_variable + 10", scope).cast<int>();
 
     // Evaluate a sequence of statements
-    py::eval<py::eval_statements>(
+    py::exec(
         "print('Hello')\n"
         "print('world!');",
         scope);
@@ -62,7 +56,7 @@
 
 .. code-block:: cpp
 
-    py::eval<py::eval_statements>(R"(
+    py::exec(R"(
         x = get_answer()
         if x == 42:
             print('Hello World!')
@@ -70,3 +64,13 @@
             print('Bye!')
         )", scope
     );
+
+.. note::
+
+    `eval` and `eval_file` accept a template parameter that describes how the
+    string/file should be interpreted. Possible choices include ``eval_expr``
+    (isolated expression), ``eval_single_statement`` (a single statement, return
+    value is always ``none``), and ``eval_statements`` (sequence of statements,
+    return value is always ``none``). `eval` defaults to  ``eval_expr``,
+    `eval_file` defaults to ``eval_statements`` and `exec` is just a shortcut
+    for ``eval<eval_statements>``.
diff --git a/include/pybind11/eval.h b/include/pybind11/eval.h
index d4d26c1..c829b0c 100644
--- a/include/pybind11/eval.h
+++ b/include/pybind11/eval.h
@@ -62,6 +62,15 @@
     return eval<mode>(expr, global, local);
 }
 
+inline void exec(str expr, object global = object(), object local = object()) {
+    eval<eval_statements>(expr, global, local);
+}
+
+template <size_t N>
+void exec(const char (&s)[N], object global = object(), object local = object()) {
+    eval<eval_statements>(s, global, local);
+}
+
 template <eval_mode mode = eval_statements>
 object eval_file(str fname, object global = object(), object local = object()) {
     if (!global) {
diff --git a/tests/test_eval.cpp b/tests/test_eval.cpp
index 9a8ac21..610d0e2 100644
--- a/tests/test_eval.cpp
+++ b/tests/test_eval.cpp
@@ -21,14 +21,14 @@
         });
 
         // Regular string literal
-        py::eval<py::eval_statements>(
+        py::exec(
             "message = 'Hello World!'\n"
             "x = call_test()",
             global, local
         );
 
         // Multi-line raw string literal
-        auto result = py::eval<py::eval_statements>(R"(
+        py::exec(R"(
             if x == 42:
                 print(message)
             else:
@@ -37,7 +37,7 @@
         );
         auto x = local["x"].cast<int>();
 
-        return result.is_none() && x == 42;
+        return x == 42;
     });
 
     m.def("test_eval", [global]() {