From 1a348b2e841b5406663114503c12c354c0811b93 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Thu, 13 Jun 2024 02:42:41 -0600 Subject: [PATCH] AVRO-3995 [C++] Requires C++17 to compile Avro (#2949) --- lang/c++/CMakeLists.txt | 4 ++ lang/c++/MainPage.dox | 4 +- lang/c++/README | 4 +- lang/c++/api/GenericDatum.hh | 61 ++++-------------------------- lang/c++/impl/avrogencpp.cc | 72 ++++++++++++++---------------------- 5 files changed, 42 insertions(+), 103 deletions(-) diff --git a/lang/c++/CMakeLists.txt b/lang/c++/CMakeLists.txt index 2d726d0ec06..522f248430c 100644 --- a/lang/c++/CMakeLists.txt +++ b/lang/c++/CMakeLists.txt @@ -24,6 +24,10 @@ if (NOT DEFINED CMAKE_CXX_STANDARD) set(CMAKE_CXX_STANDARD 17) endif() +if (CMAKE_CXX_STANDARD LESS 17) + message(FATAL_ERROR "Avro requires at least C++17") +endif() + set(CMAKE_CXX_STANDARD_REQUIRED ON) if (APPLE) diff --git a/lang/c++/MainPage.dox b/lang/c++/MainPage.dox index 0f4f0e97141..91977fca2f1 100644 --- a/lang/c++/MainPage.dox +++ b/lang/c++/MainPage.dox @@ -55,9 +55,9 @@ One should be able to build Avro C++ on (1) any UNIX flavor including cygwin for In order to build Avro C++, one needs the following: diff --git a/lang/c++/README b/lang/c++/README index caf30ce760b..be5f2ff62d7 100644 --- a/lang/c++/README +++ b/lang/c++/README @@ -29,9 +29,9 @@ INSTRUCTIONS Pre-requisites: -To compile requires boost headers, the boost regex library and the fmt library. Optionally, it requires Snappy compression library. If Snappy is available, it builds support for Snappy compression and skips it otherwise. (Please see your OS-specific instructions on how to install Boost and Snappy for your OS). +To compile requires boost headers. Optionally, it requires Snappy compression library. If Snappy is available, it builds support for Snappy compression and skips it otherwise. (Please see your OS-specific instructions on how to install Boost and Snappy for your OS). -To build one requires cmake 3.5 or later and a compiler which supports at least C++17. +To build one requires cmake 3.5 or later and a compiler supporting C++17 or later. To generate a Makefile under Unix, MacOS (using GNU) or Cygwin use: diff --git a/lang/c++/api/GenericDatum.hh b/lang/c++/api/GenericDatum.hh index a1782cf5900..a6ce2463ca8 100644 --- a/lang/c++/api/GenericDatum.hh +++ b/lang/c++/api/GenericDatum.hh @@ -19,17 +19,12 @@ #ifndef avro_GenericDatum_hh__ #define avro_GenericDatum_hh__ +#include #include #include #include #include -#if __cplusplus >= 201703L -#include -#else -#include "boost/any.hpp" -#endif - #include "LogicalType.hh" #include "Node.hh" #include "ValidSchema.hh" @@ -62,11 +57,7 @@ class AVRO_DECL GenericDatum { protected: Type type_; LogicalType logicalType_; -#if __cplusplus >= 201703L std::any value_; -#else - boost::any value_; -#endif explicit GenericDatum(Type t) : type_(t), logicalType_(LogicalType::NONE) {} @@ -192,11 +183,7 @@ public: template GenericDatum(const NodePtr &schema, const T &v) : type_(schema->type()), logicalType_(schema->logicalType()) { init(schema); -#if __cplusplus >= 201703L *std::any_cast(&value_) = v; -#else - *boost::any_cast(&value_) = v; -#endif } /** @@ -539,67 +526,33 @@ public: }; inline Type GenericDatum::type() const { - return (type_ == AVRO_UNION) ? -#if __cplusplus >= 201703L - std::any_cast(&value_)->datum().type() - : -#else - boost::any_cast(&value_)->datum().type() - : -#endif - type_; + return (type_ == AVRO_UNION) ? std::any_cast(&value_)->datum().type() + : type_; } inline LogicalType GenericDatum::logicalType() const { - return (type_ == AVRO_UNION) ? -#if __cplusplus >= 201703L - std::any_cast(&value_)->datum().logicalType() - : -#else - boost::any_cast(&value_)->datum().logicalType() - : -#endif - logicalType_; + return (type_ == AVRO_UNION) ? std::any_cast(&value_)->datum().logicalType() + : logicalType_; } template T &GenericDatum::value() { - return (type_ == AVRO_UNION) ? -#if __cplusplus >= 201703L - std::any_cast(&value_)->datum().value() + return (type_ == AVRO_UNION) ? std::any_cast(&value_)->datum().value() : *std::any_cast(&value_); -#else - boost::any_cast(&value_)->datum().value() - : *boost::any_cast(&value_); -#endif } template const T &GenericDatum::value() const { - return (type_ == AVRO_UNION) ? -#if __cplusplus >= 201703L - std::any_cast(&value_)->datum().value() + return (type_ == AVRO_UNION) ? std::any_cast(&value_)->datum().value() : *std::any_cast(&value_); -#else - boost::any_cast(&value_)->datum().value() - : *boost::any_cast(&value_); -#endif } inline size_t GenericDatum::unionBranch() const { -#if __cplusplus >= 201703L return std::any_cast(&value_)->currentBranch(); -#else - return boost::any_cast(&value_)->currentBranch(); -#endif } inline void GenericDatum::selectBranch(size_t branch) { -#if __cplusplus >= 201703L std::any_cast(&value_)->selectBranch(branch); -#else - boost::any_cast(&value_)->selectBranch(branch); -#endif } } // namespace avro diff --git a/lang/c++/impl/avrogencpp.cc b/lang/c++/impl/avrogencpp.cc index eb79873b09a..19e38062cc1 100644 --- a/lang/c++/impl/avrogencpp.cc +++ b/lang/c++/impl/avrogencpp.cc @@ -32,8 +32,6 @@ #include #include -#include - #include "Compiler.hh" #include "NodeImpl.hh" #include "ValidSchema.hh" @@ -78,8 +76,6 @@ class CodeGen { const std::string headerFile_; const std::string includePrefix_; const bool noUnion_; - const bool useCpp17_; - std::string anyNs; const std::string guardString_; boost::mt19937 random_; @@ -110,16 +106,11 @@ class CodeGen { CodeGen(std::ostream &os, std::string ns, std::string schemaFile, std::string headerFile, std::string guardString, - std::string includePrefix, bool noUnion, bool useCpp17) : unionNumber_(0), os_(os), inNamespace_(false), ns_(std::move(ns)), - schemaFile_(std::move(schemaFile)), headerFile_(std::move(headerFile)), - includePrefix_(std::move(includePrefix)), noUnion_(noUnion), useCpp17_(useCpp17), - guardString_(std::move(guardString)), - random_(static_cast(::time(nullptr))) { -#if __cplusplus >= 201703L - anyNs = "std"; -#else - anyNs = (useCpp17) ? "std" : "boost"; -#endif + std::string includePrefix, bool noUnion) : unionNumber_(0), os_(os), inNamespace_(false), ns_(std::move(ns)), + schemaFile_(std::move(schemaFile)), headerFile_(std::move(headerFile)), + includePrefix_(std::move(includePrefix)), noUnion_(noUnion), + guardString_(std::move(guardString)), + random_(static_cast(::time(nullptr))) { } void generate(const ValidSchema &schema); @@ -322,7 +313,7 @@ string CodeGen::unionName() { static void generateGetterAndSetter(ostream &os, const string &structName, const string &type, const string &name, - size_t idx, const std::string &anyNs) { + size_t idx) { string sn = " " + structName + "::"; os << "inline\n"; @@ -332,7 +323,7 @@ static void generateGetterAndSetter(ostream &os, << " throw avro::Exception(\"Invalid type for " << "union " << structName << "\");\n" << " }\n" - << " return " << anyNs << "::any_cast<" << type << " >(value_);\n" + << " return std::any_cast<" << type << " >(value_);\n" << "}\n\n"; os << "inline\n" @@ -389,7 +380,7 @@ string CodeGen::generateUnionType(const NodePtr &n) { os_ << "struct " << result << " {\n" << "private:\n" << " size_t idx_;\n" - << " " << anyNs << "::any value_;\n" + << " std::any value_;\n" << "public:\n" << " size_t idx() const { return idx_; }\n"; @@ -401,7 +392,7 @@ string CodeGen::generateUnionType(const NodePtr &n) { << " }\n" << " void set_null() {\n" << " idx_ = " << i << ";\n" - << " value_ = " << anyNs << "::any();\n" + << " value_ = std::any();\n" << " }\n"; } else { const string &type = types[i]; @@ -728,28 +719,15 @@ void CodeGen::generate(const ValidSchema &schema) { os_ << "#ifndef " << h << "\n"; os_ << "#define " << h << "\n\n\n"; - os_ << "#include \n"; -#if __cplusplus >= 201703L - os_ << "#include \n"; -#else - if (useCpp17_) - os_ << "#include \n"; - else - os_ << "#include \"boost/any.hpp\"\n"; -#endif - os_ << "#include \"" << includePrefix_ << "Specific.hh\"\n" + os_ << "#include \n" + << "#include \n" + << "#include \"" << includePrefix_ << "Specific.hh\"\n" << "#include \"" << includePrefix_ << "Encoder.hh\"\n" << "#include \"" << includePrefix_ << "Decoder.hh\"\n" << "\n"; - vector nsVector; if (!ns_.empty()) { - boost::algorithm::split_regex(nsVector, ns_, boost::regex("::")); - for (vector::const_iterator it = - nsVector.begin(); - it != nsVector.end(); ++it) { - os_ << "namespace " << *it << " {\n"; - } + os_ << "namespace " << ns_ << " {\n"; inNamespace_ = true; } @@ -760,7 +738,7 @@ void CodeGen::generate(const ValidSchema &schema) { pendingGettersAndSetters.begin(); it != pendingGettersAndSetters.end(); ++it) { generateGetterAndSetter(os_, it->structName, it->type, it->name, - it->idx, anyNs); + it->idx); } for (vector::const_iterator it = @@ -772,11 +750,7 @@ void CodeGen::generate(const ValidSchema &schema) { if (!ns_.empty()) { inNamespace_ = false; - for (vector::const_iterator it = - nsVector.begin(); - it != nsVector.end(); ++it) { - os_ << "}\n"; - } + os_ << "}\n"; } os_ << "namespace avro {\n"; @@ -822,7 +796,16 @@ int main(int argc, char **argv) { const string NO_UNION_TYPEDEF("no-union-typedef"); po::options_description desc("Allowed options"); - desc.add_options()("help,h", "produce help message")("version,V", "produce version information")("include-prefix,p", po::value()->default_value("avro"), "prefix for include headers, - for none, default: avro")("no-union-typedef,U", "do not generate typedefs for unions in records")("namespace,n", po::value(), "set namespace for generated code")("cpp17", "use c++17 instead of boost")("input,i", po::value(), "input file")("output,o", po::value(), "output file to generate"); + // clang-format off + desc.add_options() + ("help,h", "produce help message") + ("version,V", "produce version information") + ("include-prefix,p", po::value()->default_value("avro"), "prefix for include headers, - for none, default: avro") + ("no-union-typedef,U", "do not generate typedefs for unions in records") + ("namespace,n", po::value(), "set namespace for generated code") + ("input,i", po::value(), "input file") + ("output,o", po::value(), "output file to generate"); + // clang-format on po::variables_map vm; po::store(po::parse_command_line(argc, argv, desc), vm); @@ -848,7 +831,6 @@ int main(int argc, char **argv) { string inf = vm.count(IN_FILE) > 0 ? vm[IN_FILE].as() : string(); string incPrefix = vm[INCLUDE_PREFIX].as(); bool noUnion = vm.count(NO_UNION_TYPEDEF) != 0; - bool useCpp17 = vm.count("cpp17") != 0; if (incPrefix == "-") { incPrefix.clear(); @@ -869,9 +851,9 @@ int main(int argc, char **argv) { if (!outf.empty()) { string g = readGuard(outf); ofstream out(outf.c_str()); - CodeGen(out, ns, inf, outf, g, incPrefix, noUnion, useCpp17).generate(schema); + CodeGen(out, ns, inf, outf, g, incPrefix, noUnion).generate(schema); } else { - CodeGen(std::cout, ns, inf, outf, "", incPrefix, noUnion, useCpp17).generate(schema); + CodeGen(std::cout, ns, inf, outf, "", incPrefix, noUnion).generate(schema); } return 0; } catch (std::exception &e) {