You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Public headers require C++23, forcing the same on every consumer #928
CMakeLists.txt:35 sets CMAKE_CXX_STANDARD 23, which is a fine choice for the
library's own sources. The requirement is not confined to them, though. src/iceberg/result.h includes <expected> and <format>, and defines:
template <typename T, typename E = typename DefaultError<T>::type>
using Result = std::expected<T, E>;
using Status = Result<void>;
Result<T> is the return type of most public entry points — Catalog::ListNamespaces, ListTables, LoadTable, CreateTable, StageCreateTable and so on. Every consumer translation unit that calls them
must therefore compile as C++23 as well. std::expected needs libstdc++ 12 or
libc++ 16 and <format> needs libstdc++ 13, so a consumer on an older but still
widely deployed toolchain cannot include the headers at all.
This matters for the engines the library is meant to be embedded in: Velox
builds as C++20, Arrow as C++17, DuckDB as C++11. Integrating leaves two
options — move the whole engine to C++23, or add an isolation layer whose only
purpose is keeping iceberg-cpp headers out of the rest of the build. We are
looking at iceberg-cpp for an Iceberg connector in Axiom, which builds on Velox at
C++20, and would rather do neither.
Would you consider making the public error type portable while keeping the API
shape unchanged?
#if defined(__cpp_lib_expected)
template <typename T, typename E = typename DefaultError<T>::type>
using Result = std::expected<T, E>;
#else// vendored fallback with the same interface
#endif
arrow::Result, absl::StatusOr and tl::expected all exist for this reason.
The library's own sources could keep building as C++23; only the public headers
would need to hold a lower baseline.
Happy to send a patch if the direction is agreeable.
cc @PingLiuPing, who is proposing the Iceberg connector for Axiom.
IMHO, it would be more than welcome if such changes can broaden the adoption of iceberg-cpp. My concern is that fixing only <expected> and <format> is not enough. We have ported #40 but it got removed once we bump to C++23. Do you want to explore a PoC to see if it is possible? @mbasmanova@PingLiuPing
IMHO, it would be more than welcome if such changes can broaden the adoption of iceberg-cpp. My concern is that fixing only <expected> and <format> is not enough. We have ported #40 but it got removed once we bump to C++23. Do you want to explore a PoC to see if it is possible? @mbasmanova@PingLiuPing
I'm open to downgrading to C++20 if that would make it easier for other engines to adopt iceberg-cpp, especially at this early stage ( adoption is still limited :-)).
I am fine with wrapping an additional interface that compiles with an older C++ standard, but I do not want to downgrade the project's C++ version.
#if defined(__cpp_lib_expected)
template <typename T, typename E = typename DefaultError::type>
using Result = std::expected<T, E>;
#else
// vendored fallback with the same interface
#endif
I am also fine with this approach if we can centrally manage these definitions.
Thanks @mbasmanova for filing this issue. Result and Status in result.h are exactly where the C++23 requirement reaches consumers.
And thanks @wgtmac, @zhjwpku and @HuaHuaY for the quick and thoughtful replies.
To be explicit about what we are asking for: we only want the public headers to be portable. We are not proposing to lower the project's own C++ standard. iceberg-cpp would keep building as C++23; the .cc files and the *_internal.h headers keep using C++23. Only the headers a consumer actually include would hold a lower standard. This matches what @HuaHuaY asked for, a wrapper rather than a downgrade.
Two options in this thread
Portable C++ headers at a C++20 baseline — @mbasmanova's proposal: a vendored expected with the same interface behind Result and Status, with the library itself staying on C++23. As @wgtmac pointed out, <expected> and <format> alone are not enough for a consumer to actually include the headers, so this also means removing other C++23 features from them. The result is a C++20 baseline for the public headers.
A C API, as @zhjwpku suggested, in the style of RocksDB.
The two are not exclusive: a C API would also be the only thing that reaches the C++17 and C++11 consumers. Compiling the public headers at C++17 gives 32 of 205 passing, and the blockers are:
feature
public headers using it
std::span in signatures
31
requires clauses
15
std::format / <format>
11
concept definitions
8
std::remove_cvref_t
6
operator<=>
2
consteval
1
Reaching C++17 would mean more work.
I have a branch that go with option 1, and the complexity is modest: 48 files, +264 / −136 lines excluding the restored vendored file and its test:
Replace std::unreachable in 11 public headers, std::ranges::to in 2 and std::byteswap in 1.
Drop deducing this from TaskGroup (ref-qualified overloads) and from ErrorCollector::AddError (chaining on *this, which is already the derived
type).
Build example/ as C++20 in CI, so a public header cannot silently pick up a
C++23 feature again — it is already built on Linux, macOS and Windows against
the installed package, which is exactly a consumer's view.
Verified locally: all 205 public headers compile standalone as C++20, the library
still builds as C++23, and the test suites pass (1878 tests across util_test, schema_test, table_test, expression_test, json_serde_test), including the
26 tests in the restored expected_test.cc.
Let me know if this is the right direction you want to go? Thanks.
Hi @PingLiuPing. Thanks for your work. It sounds like you've already finished most of the work. Can you open a PR or a draft PR? I think this will be helpful for a better review of the design proposal.
Hi @PingLiuPing. Thanks for your work. It sounds like you've already finished most of the work. Can you open a PR or a draft PR? I think this will be helpful for a better review of the design proposal.
Activity
wgtmac commentedon Sep 9, 2026
IMHO, it would be more than welcome if such changes can broaden the adoption of iceberg-cpp. My concern is that fixing only
<expected>and<format>is not enough. We have ported #40 but it got removed once we bump to C++23. Do you want to explore a PoC to see if it is possible? @mbasmanova @PingLiuPingcc @zhjwpku @manuzhang @HuaHuaY
zhjwpku commentedon Sep 9, 2026
I'm open to downgrading to C++20 if that would make it easier for other engines to adopt iceberg-cpp, especially at this early stage ( adoption is still limited :-)).
HuaHuaY commentedon Sep 9, 2026
I am fine with wrapping an additional interface that compiles with an older C++ standard, but I do not want to downgrade the project's C++ version.
I am also fine with this approach if we can centrally manage these definitions.
zhjwpku commentedon Sep 10, 2026
That could be another option. We could expose a C API, like RocksDB does, to make it easier for more projects to adopt iceberg-cpp.
PingLiuPing commentedon Sep 14, 2026
Thanks @mbasmanova for filing this issue.
ResultandStatusinresult.hare exactly where the C++23 requirement reaches consumers.And thanks @wgtmac, @zhjwpku and @HuaHuaY for the quick and thoughtful replies.
To be explicit about what we are asking for: we only want the public headers to be portable. We are not proposing to lower the project's own C++ standard. iceberg-cpp would keep building as C++23; the
.ccfiles and the*_internal.hheaders keep using C++23. Only the headers a consumer actually include would hold a lower standard. This matches what @HuaHuaY asked for, a wrapper rather than a downgrade.Two options in this thread
expectedwith the same interface behindResultandStatus, with the library itself staying on C++23. As @wgtmac pointed out,<expected>and<format>alone are not enough for a consumer to actually include the headers, so this also means removing other C++23 features from them. The result is a C++20 baseline for the public headers.The two are not exclusive: a C API would also be the only thing that reaches the C++17 and C++11 consumers. Compiling the public headers at C++17 gives
32 of 205 passing, and the blockers are:
std::spanin signaturesrequiresclausesstd::format/<format>conceptdefinitionsstd::remove_cvref_toperator<=>constevalReaching C++17 would mean more work.
I have a branch that go with option 1, and the complexity is modest: 48 files, +264 / −136 lines excluding the restored vendored file and its test:
src/iceberg/expected.hfrom backport c++23 std::expected #40 (removed by chore: bump C++ standard to 23 #139) and aliasResultto it unconditionally. The library's own errors become
iceberg::unexpected.std::unreachablein 11 public headers,std::ranges::toin 2 andstd::byteswapin 1.thisfromTaskGroup(ref-qualified overloads) and fromErrorCollector::AddError(chaining on*this, which is already the derivedtype).
example/as C++20 in CI, so a public header cannot silently pick up aC++23 feature again — it is already built on Linux, macOS and Windows against
the installed package, which is exactly a consumer's view.
Verified locally: all 205 public headers compile standalone as C++20, the library
still builds as C++23, and the test suites pass (1878 tests across
util_test,schema_test,table_test,expression_test,json_serde_test), including the26 tests in the restored
expected_test.cc.Let me know if this is the right direction you want to go? Thanks.
HuaHuaY commentedon Sep 14, 2026
Hi @PingLiuPing. Thanks for your work. It sounds like you've already finished most of the work. Can you open a PR or a draft PR? I think this will be helpful for a better review of the design proposal.
PingLiuPing commentedon Sep 17, 2026
@HuaHuaY Thanks, submitted PR #936.
feat: make public headers consumable as C++20 in compat mode (apache#936