diff --git a/bindings/cxx/examples/.gitignore b/bindings/cxx/examples/.gitignore
new file mode 100644
index 0000000..54bda46
--- /dev/null
+++ b/bindings/cxx/examples/.gitignore
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
+
+gpiodetectcxx
+gpiofindcxx
+gpiogetcxx
+gpioinfocxx
+gpiomoncxx
+gpiosetcxx
diff --git a/bindings/cxx/examples/Makefile.am b/bindings/cxx/examples/Makefile.am
new file mode 100644
index 0000000..04cd64a
--- /dev/null
+++ b/bindings/cxx/examples/Makefile.am
@@ -0,0 +1,26 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
+
+AM_CPPFLAGS = -I$(top_srcdir)/bindings/cxx/ -I$(top_srcdir)/include
+AM_CPPFLAGS += -Wall -Wextra -g -std=gnu++17
+AM_LDFLAGS = -lgpiodcxx -L$(top_builddir)/bindings/cxx/
+
+noinst_PROGRAMS = \
+		gpiodetectcxx \
+		gpiofindcxx \
+		gpiogetcxx \
+		gpioinfocxx \
+		gpiomoncxx \
+		gpiosetcxx
+
+gpiodetectcxx_SOURCES = gpiodetectcxx.cpp
+
+gpiofindcxx_SOURCES = gpiofindcxx.cpp
+
+gpiogetcxx_SOURCES = gpiogetcxx.cpp
+
+gpioinfocxx_SOURCES = gpioinfocxx.cpp
+
+gpiomoncxx_SOURCES = gpiomoncxx.cpp
+
+gpiosetcxx_SOURCES = gpiosetcxx.cpp
diff --git a/bindings/cxx/examples/gpiodetectcxx.cpp b/bindings/cxx/examples/gpiodetectcxx.cpp
new file mode 100644
index 0000000..7dbb0e0
--- /dev/null
+++ b/bindings/cxx/examples/gpiodetectcxx.cpp
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
+
+/* C++ reimplementation of the gpiodetect tool. */
+
+#include <cstdlib>
+#include <filesystem>
+#include <gpiod.hpp>
+#include <iostream>
+
+int main(int argc, char **argv)
+{
+	if (argc != 1) {
+		::std::cerr << "usage: " << argv[0] << ::std::endl;
+		return EXIT_FAILURE;
+	}
+
+	for (const auto& entry: ::std::filesystem::directory_iterator("/dev/")) {
+		if (::gpiod::is_gpiochip_device(entry.path())) {
+			::gpiod::chip chip(entry.path());
+			auto info = chip.get_info();
+
+			::std::cout << info.name() << " [" <<
+				       info.label() << "] (" <<
+				       info.num_lines() << " lines)" << ::std::endl;
+		}
+	}
+
+	return EXIT_SUCCESS;
+}
diff --git a/bindings/cxx/examples/gpiofindcxx.cpp b/bindings/cxx/examples/gpiofindcxx.cpp
new file mode 100644
index 0000000..cd36be7
--- /dev/null
+++ b/bindings/cxx/examples/gpiofindcxx.cpp
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
+
+/* C++ reimplementation of the gpiofind tool. */
+
+#include <gpiod.hpp>
+
+#include <cstdlib>
+#include <filesystem>
+#include <iostream>
+
+int main(int argc, char **argv)
+{
+	if (argc != 2) {
+		::std::cerr << "usage: " << argv[0] << " <line name>" << ::std::endl;
+		return EXIT_FAILURE;
+	}
+
+	for (const auto& entry: ::std::filesystem::directory_iterator("/dev/")) {
+		if (::gpiod::is_gpiochip_device(entry.path())) {
+			::gpiod::chip chip(entry.path());
+
+			auto offset = chip.get_line_offset_from_name(argv[1]);
+			if (offset >= 0) {
+				::std::cout << chip.get_info().name() << " " << offset << ::std::endl;
+				return EXIT_SUCCESS;
+			}
+		}
+	}
+
+	return EXIT_FAILURE;
+}
diff --git a/bindings/cxx/examples/gpiogetcxx.cpp b/bindings/cxx/examples/gpiogetcxx.cpp
new file mode 100644
index 0000000..0136f5f
--- /dev/null
+++ b/bindings/cxx/examples/gpiogetcxx.cpp
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
+
+/* Simplified C++ reimplementation of the gpioget tool. */
+
+#include <gpiod.hpp>
+
+#include <cstdlib>
+#include <iostream>
+
+int main(int argc, char **argv)
+{
+	if (argc < 3) {
+		::std::cerr << "usage: " << argv[0] << " <chip> <line_offset0> ..." << ::std::endl;
+		return EXIT_FAILURE;
+	}
+
+	::gpiod::line::offsets offsets;
+
+	for (int i = 2; i < argc; i++)
+		offsets.push_back(::std::stoul(argv[i]));
+
+	::gpiod::chip chip(argv[1]);
+	auto request = chip.request_lines(
+			::gpiod::request_config({
+				{ ::gpiod::request_config::property::OFFSETS, offsets },
+				{ ::gpiod::request_config::property::CONSUMER, "gpiogetcxx" }
+			}),
+			::gpiod::line_config());
+
+	auto vals = request.get_values();
+
+	for (auto& it: vals)
+		::std::cout << (it == ::gpiod::line::value::ACTIVE ? "1" : "0") << ' ';
+	::std::cout << ::std::endl;
+
+	return EXIT_SUCCESS;
+}
diff --git a/bindings/cxx/examples/gpioinfocxx.cpp b/bindings/cxx/examples/gpioinfocxx.cpp
new file mode 100644
index 0000000..3612092
--- /dev/null
+++ b/bindings/cxx/examples/gpioinfocxx.cpp
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
+
+/* Simplified C++ reimplementation of the gpioinfo tool. */
+
+#include <gpiod.hpp>
+
+#include <cstdlib>
+#include <filesystem>
+#include <iostream>
+
+namespace {
+
+void show_chip(const ::gpiod::chip& chip)
+{
+	auto info = chip.get_info();
+
+	::std::cout << info.name() << " - " << info.num_lines() << " lines:" << ::std::endl;
+
+	for (unsigned int offset = 0; offset < info.num_lines(); offset++) {
+		auto info = chip.get_line_info(offset);
+
+		::std::cout << "\tline ";
+		::std::cout.width(3);
+		::std::cout << info.offset() << ": ";
+
+		::std::cout.width(12);
+		::std::cout << (info.name().empty() ? "unnamed" : info.name());
+		::std::cout << " ";
+
+		::std::cout.width(12);
+		::std::cout << (info.consumer().empty() ? "unused" : info.consumer());
+		::std::cout << " ";
+
+		::std::cout.width(8);
+		::std::cout << (info.direction() == ::gpiod::line::direction::INPUT ? "input" : "output");
+		::std::cout << " ";
+
+		::std::cout.width(10);
+		::std::cout << (info.active_low() ? "active-low" : "active-high");
+
+		::std::cout << ::std::endl;
+	}
+}
+
+} /* namespace */
+
+int main(int argc, char **argv)
+{
+	if (argc != 1) {
+		::std::cerr << "usage: " << argv[0] << ::std::endl;
+		return EXIT_FAILURE;
+	}
+
+	for (const auto& entry: ::std::filesystem::directory_iterator("/dev/")) {
+		if (::gpiod::is_gpiochip_device(entry.path()))
+			show_chip(::gpiod::chip(entry.path()));
+	}
+
+	return EXIT_SUCCESS;
+}
diff --git a/bindings/cxx/examples/gpiomoncxx.cpp b/bindings/cxx/examples/gpiomoncxx.cpp
new file mode 100644
index 0000000..db053dd
--- /dev/null
+++ b/bindings/cxx/examples/gpiomoncxx.cpp
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
+
+/* Simplified C++ reimplementation of the gpiomon tool. */
+
+#include <chrono>
+#include <cstdlib>
+#include <gpiod.hpp>
+#include <iostream>
+
+namespace {
+
+void print_event(const ::gpiod::edge_event& event)
+{
+	if (event.type() == ::gpiod::edge_event::event_type::RISING_EDGE)
+		::std::cout << " RISING EDGE";
+	else
+		::std::cout << "FALLING EDGE";
+
+	::std::cout << " ";
+
+	::std::cout << event.timestamp_ns() / 1000000000;
+	::std::cout << ".";
+	::std::cout << event.timestamp_ns() % 1000000000;
+
+	::std::cout << " line: " << event.line_offset();
+
+	::std::cout << ::std::endl;
+}
+
+} /* namespace */
+
+int main(int argc, char **argv)
+{
+	if (argc < 3) {
+		::std::cout << "usage: " << argv[0] << " <chip> <offset0> ..." << ::std::endl;
+		return EXIT_FAILURE;
+	}
+
+	::gpiod::line::offsets offsets;
+	offsets.reserve(argc);
+	for (int i = 2; i < argc; i++)
+		offsets.push_back(::std::stoul(argv[i]));
+
+	::gpiod::chip chip(argv[1]);
+	auto request = chip.request_lines(
+			::gpiod::request_config({
+				{ ::gpiod::request_config::property::OFFSETS, offsets},
+				{ ::gpiod::request_config::property::CONSUMER, "gpiomoncxx"},
+			}),
+			::gpiod::line_config({
+				{
+					::gpiod::line_config::property::DIRECTION,
+					::gpiod::line::direction::INPUT
+				},
+				{
+					::gpiod::line_config::property::EDGE,
+					::gpiod::line::edge::BOTH
+				}
+			}));
+
+	::gpiod::edge_event_buffer buffer;
+
+	for (;;) {
+		if (request.wait_edge_event(::std::chrono::seconds(5))) {
+			request.read_edge_event(buffer);
+
+			for (const auto& event: buffer)
+				print_event(event);
+		}
+	}
+
+	return EXIT_SUCCESS;
+}
diff --git a/bindings/cxx/examples/gpiosetcxx.cpp b/bindings/cxx/examples/gpiosetcxx.cpp
new file mode 100644
index 0000000..838d801
--- /dev/null
+++ b/bindings/cxx/examples/gpiosetcxx.cpp
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-FileCopyrightText: 2017-2021 Bartosz Golaszewski <bartekgola@gmail.com>
+
+/* Simplified C++ reimplementation of the gpioset tool. */
+
+#include <gpiod.hpp>
+
+#include <cstdlib>
+#include <iostream>
+
+int main(int argc, char **argv)
+{
+	if (argc < 3) {
+		::std::cerr << "usage: " << argv[0] <<
+			       " <chip> <line_offset0>=<value0> ..." << ::std::endl;
+		return EXIT_FAILURE;
+	}
+
+	::gpiod::line::offsets offsets;
+	::gpiod::line::values values;
+
+	for (int i = 2; i < argc; i++) {
+		::std::string arg(argv[i]);
+
+		size_t pos = arg.find('=');
+
+		::std::string offset(arg.substr(0, pos));
+		::std::string value(arg.substr(pos + 1, ::std::string::npos));
+
+		if (offset.empty() || value.empty())
+			throw ::std::invalid_argument("invalid offset=value mapping: " +
+						      ::std::string(argv[i]));
+
+		offsets.push_back(::std::stoul(offset));
+		values.push_back(::std::stoul(value) ? ::gpiod::line::value::ACTIVE :
+						       ::gpiod::line::value::INACTIVE);
+	}
+
+	::gpiod::chip chip(argv[1]);
+	auto request = chip.request_lines(
+			::gpiod::request_config({
+				{ ::gpiod::request_config::property::OFFSETS, offsets },
+				{ ::gpiod::request_config::property::CONSUMER, "gpiogetcxx" }
+			}),
+			::gpiod::line_config({
+				{
+					::gpiod::line_config::property::DIRECTION,
+					::gpiod::line::direction::OUTPUT
+				}
+			}));
+
+	request.set_values(values);
+
+	::std::cin.get();
+
+	return EXIT_SUCCESS;
+}
