TL;DR
- Current DuckDB main requires C++17 or higher. C++11 is no longer a supported baseline.
- This is not only a build-system preference. Common headers already use C++17 features.
- The important features are
std::string_view,std::optional,if constexpr, type-traits_vhelpers, structured bindings, and a small amount ofstd::variant.
The direct test
DuckDB's Makefile still exposes a CXX_STANDARD override:
ifneq (${CXX_STANDARD}, )
CMAKE_VARS:=${CMAKE_VARS} -DCMAKE_CXX_STANDARD="${CXX_STANDARD}"
endif
So the direct test is:
CXX_STANDARD=11 GEN=ninja make debug
On the tested DuckDB main snapshot, this fails during CMake configuration:
DuckDB requires C++17 or higher; got CMAKE_CXX_STANDARD=11.
Pass -DCMAKE_CXX_STANDARD=17 (or higher), or unset it to use the default.
The project boundary is explicit. DuckDB accepts C++17, C++20, C++23, and C++26. It does not accept C++11.
Why that boundary exists
The CMake error proves that C++11 is unsupported, but it does not explain why the source wants C++17.
For that, I generated normal C++17 compile commands and rewrote selected real commands to -std=c++11 -fsyntax-only. The first hard errors came from common headers:
src/include/duckdb/common/helper.hpp: error: 'is_same_v' is not a member of 'std'
src/include/duckdb/common/identifier.hpp: error: 'string_view' in namespace 'std' does not name a type
src/include/duckdb/common/optional.hpp: error: 'nullopt' has not been declared in 'std'
src/include/duckdb/common/optional.hpp: error: 'optional' has not been declared in 'std'
src/include/duckdb/common/types/value.hpp: error: 'optional' does not name a type
So this is not a codebase that mostly compiles as C++11. It fails soon after common headers are parsed.
The features are already spread out
A source scan of the same snapshot found these rough counts:
| Feature | Rough hits | Typical places |
|---|---|---|
if constexpr | 185 | casts, aggregates, recursive CTE, template executors |
std::string_view / string_view | 111 | identifiers, Value, C API v2, settings |
std::optional | 19 | common optional wrapper, cast/result paths |
| structured bindings | 17 | bind helpers, copy path, function serialization |
std::variant | 1 | bitpacking compression state |
These are better reasons than "modern C++ is nicer".
std::string_view avoids unnecessary string allocation and copying. A database has identifiers, settings, function names, and literal buffers everywhere.
std::optional expresses "there may be no value" without sentinel values, raw pointers, or a separate boolean.
if constexpr matters for DuckDB's template-heavy primitives. A normal if still requires both branches to type-check. if constexpr lets the compiler discard the branch that does not apply to the current type.
The _v type-traits helpers are small but common. C++11 can spell them as std::is_same<T, U>::value, but current DuckDB code is already written in the C++17 form.
Boundary
The claim here is narrow:
C++11 was enough to start the project.
C++17 is now the minimum boundary for expressing and compiling current DuckDB code directly.
This does not mean every C++17 feature is good for database code. It only means the current DuckDB source has crossed the line where C++11 compatibility is still realistic.