diff --git a/CMakeLists.txt b/CMakeLists.txt index aea72fd2..f0138d62 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -189,7 +189,7 @@ if(ENABLE_LEGACY) set(cyclonedds_cpp_std_to_use 11) set(DDSCXX_USE_BOOST "1") find_package(Boost) - include_directories(${Boost_INCLUDE_DIR}) + include_directories(SYSTEM ${Boost_INCLUDE_DIR}) endif() include(CMakePackageConfigHelpers) diff --git a/examples/helloworld/CMakeLists.txt b/examples/helloworld/CMakeLists.txt index f3ccc7d3..ecf0335c 100644 --- a/examples/helloworld/CMakeLists.txt +++ b/examples/helloworld/CMakeLists.txt @@ -12,6 +12,8 @@ project(helloworld LANGUAGES C CXX) cmake_minimum_required(VERSION 3.16) +set(CMAKE_CXX_STANDARD 17) + if(NOT TARGET CycloneDDS-CXX::ddscxx) find_package(CycloneDDS-CXX REQUIRED) endif() diff --git a/examples/helloworld/publisher.cpp b/examples/helloworld/publisher.cpp index 5e4c3f80..64775d53 100644 --- a/examples/helloworld/publisher.cpp +++ b/examples/helloworld/publisher.cpp @@ -54,7 +54,7 @@ int main() { HelloWorldData::Msg msg(1, "Hello World"); /* Write the message. */ - std::cout << "=== [Publisher] Write sample." << std::endl; + std::cout << "=== [Publisher] Write sample: " << msg << std::endl; writer.write(msg); /* With a normal configuration (see dds::pub::qos::DataWriterQos diff --git a/examples/helloworld/subscriber.cpp b/examples/helloworld/subscriber.cpp index 73a4d6d4..80ad7822 100644 --- a/examples/helloworld/subscriber.cpp +++ b/examples/helloworld/subscriber.cpp @@ -72,9 +72,7 @@ int main() { * is set. The other data parts are not. * Check if this sample has valid data. */ if (info.valid()) { - std::cout << "=== [Subscriber] Message received:" << std::endl; - std::cout << " userID : " << msg.userID() << std::endl; - std::cout << " Message : \"" << msg.message() << "\"" << std::endl; + std::cout << "=== [Subscriber] Message received: " << msg << std::endl; /* Only 1 message is expected in this example. */ poll = false; diff --git a/examples/roundtrip/CMakeLists.txt b/examples/roundtrip/CMakeLists.txt index bf27f18a..0c584c87 100644 --- a/examples/roundtrip/CMakeLists.txt +++ b/examples/roundtrip/CMakeLists.txt @@ -12,6 +12,8 @@ project(throughput LANGUAGES C CXX) cmake_minimum_required(VERSION 3.16) +set(CMAKE_CXX_STANDARD 17) + if(NOT TARGET CycloneDDS-CXX::ddscxx) find_package(CycloneDDS-CXX REQUIRED) endif() diff --git a/examples/throughput/CMakeLists.txt b/examples/throughput/CMakeLists.txt index 1236ccb6..6c028e8a 100644 --- a/examples/throughput/CMakeLists.txt +++ b/examples/throughput/CMakeLists.txt @@ -12,6 +12,8 @@ project(throughput LANGUAGES C CXX) cmake_minimum_required(VERSION 3.16) +set(CMAKE_CXX_STANDARD 17) + if(NOT TARGET CycloneDDS-CXX::ddscxx) find_package(CycloneDDS-CXX REQUIRED) endif() diff --git a/src/ddscxx/include/org/eclipse/cyclonedds/util/ostream_operators.hpp b/src/ddscxx/include/org/eclipse/cyclonedds/util/ostream_operators.hpp new file mode 100644 index 00000000..c0ad3e4f --- /dev/null +++ b/src/ddscxx/include/org/eclipse/cyclonedds/util/ostream_operators.hpp @@ -0,0 +1,74 @@ +// Copyright(c) 2006 to 2020 ZettaScale Technology and others +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License v. 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License +// v. 1.0 which is available at +// http://www.eclipse.org/org/documents/edl-v10.php. +// +// SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + +/** + * @file + */ + +#ifndef CYCLONEDDS_UTIL_OSTREAM_OPERATORS_HPP_ +#define CYCLONEDDS_UTIL_OSTREAM_OPERATORS_HPP_ + +#include "dds/features.hpp" + +#include +#include +#if DDSCXX_USE_BOOST +#include +#define DDSCXX_STD_IMPL boost +#else +#include +#define DDSCXX_STD_IMPL std +#endif + + +namespace std +{ + +template +std::ostream& operator<<(std::ostream& os, const std::array& rhs) +{ + os << "["; + for (std::size_t i = 0; i < N; i++) + { + os << rhs[i]; + if (i < N - 1) + { + os << ", "; + } + } + os << "]"; + return os; +} + +template +std::ostream& operator<<(std::ostream& os, const std::vector& rhs) +{ + os << "["; + for(size_t i=0; i +std::ostream& operator<<(std::ostream& os, const DDSCXX_STD_IMPL::optional& rhs) +{ + return rhs ? os << rhs.value() : os; +} + +} //namespace std + +#endif /* CYCLONEDDS_UTIL_OSTREAM_OPERATORS_HPP_ */ diff --git a/src/idlcxx/src/generator.c b/src/idlcxx/src/generator.c index 6971161f..b0d2bfc1 100644 --- a/src/idlcxx/src/generator.c +++ b/src/idlcxx/src/generator.c @@ -861,8 +861,9 @@ generate_includes(const idl_pstate_t *pstate, struct generator *generator) } { int len = 0; - const char *incs[11]; + const char *incs[12]; incs[len++] = ""; + incs[len++] = ""; if (generator->uses_integers) incs[len++] = ""; @@ -898,6 +899,16 @@ generate_includes(const idl_pstate_t *pstate, struct generator *generator) if (fputs("\n", generator->header.handle) < 0) return IDL_RETCODE_NO_MEMORY; + if (generator->uses_array || generator->uses_sequence || generator->uses_bounded_sequence || generator->uses_optional) + { + // ostream cpp + // streaming operators for the used std types + const char *fmt; + fmt = "#include \n\n"; + if (fputs(fmt, generator->impl.handle) < 0) + return IDL_RETCODE_NO_MEMORY; + } + return IDL_RETCODE_OK; } diff --git a/src/idlcxx/src/types.c b/src/idlcxx/src/types.c index 6ca78334..406155a2 100644 --- a/src/idlcxx/src/types.c +++ b/src/idlcxx/src/types.c @@ -129,6 +129,13 @@ emit_parameter( return IDL_RETCODE_NO_MEMORY; if (idl_fprintf(gen->header.handle, fmt, sep, type, name, eofmt) < 0) return IDL_RETCODE_NO_MEMORY; + + // ostream - cpp + fmt = " os << \"%1$s%2$s: \" << rhs.%2$s();\n"; + sep = is_first(node) ? "" : ", "; + if (idl_fprintf(gen->impl.handle, fmt, sep, name) < 0) + return IDL_RETCODE_NO_MEMORY; + return IDL_RETCODE_OK; } @@ -263,6 +270,13 @@ emit_struct( return IDL_RETCODE_NO_MEMORY; } + // ostream - cpp + fmt = "std::ostream& operator<<(std::ostream& os, %s const& rhs)\n{\n" + " (void) rhs;\n" + " os << \"[\";\n"; + if (idl_fprintf(gen->impl.handle, fmt, name) < 0) + return IDL_RETCODE_NO_MEMORY; + if (fputs("{\nprivate:\n", gen->header.handle) < 0) return IDL_RETCODE_NO_MEMORY; @@ -326,6 +340,11 @@ emit_struct( fmt = "%2$s static_cast(*this) == static_cast(_other)"; if (idl_fprintf(gen->header.handle, fmt, base, _struct->members ? " &&\n " : "") < 0) return IDL_RETCODE_NO_MEMORY; + + // ostream cpp + fmt = " os << \"%2$s%1$s: \" << static_cast(rhs);\n"; + if (idl_fprintf(gen->impl.handle, fmt, base, _struct->members ? ", " : "") < 0) + return IDL_RETCODE_NO_MEMORY; } if (!_struct->members && @@ -345,6 +364,15 @@ emit_struct( if (fputs("\n};\n\n", gen->header.handle) < 0) return IDL_RETCODE_NO_MEMORY; + // ostream - hpp + fmt = "std::ostream& operator<<(std::ostream& os, %s const& rhs);\n\n"; + if (idl_fprintf(gen->header.handle, fmt, name) < 0) + return IDL_RETCODE_NO_MEMORY; + + // ostream - cpp + if (fputs(" os << \"]\";\n return os;\n}\n\n", gen->impl.handle) < 0) + return IDL_RETCODE_NO_MEMORY; + return IDL_RETCODE_OK; } @@ -370,12 +398,28 @@ emit_enum( if (idl_fprintf(gen->header.handle, "enum class %s\n{\n", name) < 0) return IDL_RETCODE_NO_MEMORY; + // ostream cpp + fmt = "std::ostream& operator<<(std::ostream& os, %s const& rhs)\n{\n" + " (void) rhs;\n" + " switch (rhs)\n {\n"; + if (idl_fprintf(gen->impl.handle, fmt, name) < 0) + return IDL_RETCODE_NO_MEMORY; + + const char* struct_name = get_cpp11_name(node); + IDL_FOREACH(enumerator, _enum->enumerators) { name = get_cpp11_name(enumerator); value = enumerator->value.value; fmt = (value == skip) ? "%s%s" : "%s%s = %" PRIu32 "\n"; if (idl_fprintf(gen->header.handle, fmt, sep, name, value) < 0) return IDL_RETCODE_NO_MEMORY; + + // ostream cpp + fmt = " case %2$s::%1$s:\n" + " os << \"%2$s::%1$s\"; break;\n"; + if (idl_fprintf(gen->impl.handle, fmt, name, struct_name) < 0) + return IDL_RETCODE_NO_MEMORY; + skip = value + 1; sep = ",\n "; } @@ -383,6 +427,14 @@ emit_enum( if (fputs("};\n\n", gen->header.handle) < 0) return IDL_RETCODE_NO_MEMORY; + // ostream cpp + if (fputs(" default: break;\n }\n return os;\n}\n\n", gen->impl.handle) < 0) + return IDL_RETCODE_NO_MEMORY; + + // ostream hpp + if (idl_fprintf(gen->header.handle, "std::ostream& operator<<(std::ostream& os, %s const& rhs);\n\n", struct_name) < 0) + return IDL_RETCODE_NO_MEMORY; + return IDL_VISIT_DONT_RECURSE; } @@ -447,13 +499,22 @@ emit_module( (void)pstate; (void)path; + name = get_cpp11_name(node); if (revisit) { - if (fputs("}\n\n", gen->header.handle) < 0) + if (idl_fprintf(gen->header.handle, "} //namespace %s\n\n", name) < 0) + return IDL_RETCODE_NO_MEMORY; + + // ostream cpp + if (idl_fprintf(gen->impl.handle, "} //namespace %s\n\n", name) < 0) return IDL_RETCODE_NO_MEMORY; } else { - name = get_cpp11_name(node); if (idl_fprintf(gen->header.handle, "namespace %s\n{\n", name) < 0) return IDL_RETCODE_NO_MEMORY; + + // ostream cpp + if (idl_fprintf(gen->impl.handle, "namespace %s\n{\n", name) < 0) + return IDL_RETCODE_NO_MEMORY; + return IDL_VISIT_REVISIT; } @@ -570,6 +631,8 @@ emit_case( return IDL_RETCODE_OK; } +static bool gen_ostream_case = false; + static idl_retcode_t emit_case_label( const idl_pstate_t *pstate, @@ -593,9 +656,23 @@ emit_case_label( { if (idl_fprintf(gen->header.handle, " default:\n") < 0) return IDL_RETCODE_NO_MEMORY; - } else if (idl_fprintf(gen->header.handle, " case %s:\n", value) < 0) - return IDL_RETCODE_NO_MEMORY; + // ostream cpp + if (gen_ostream_case) { + if (idl_fprintf(gen->impl.handle, " default:\n") < 0) + return IDL_RETCODE_NO_MEMORY; + } + + } else { + if (idl_fprintf(gen->header.handle, " case %s:\n", value) < 0) + return IDL_RETCODE_NO_MEMORY; + + // ostream cpp + if (gen_ostream_case) { + if (idl_fprintf(gen->impl.handle, " case %s:\n", value) < 0) + return IDL_RETCODE_NO_MEMORY; + } + } return IDL_RETCODE_OK; } @@ -621,6 +698,11 @@ emit_case_comparison( if (idl_fprintf(gen->header.handle, fmt, branch_name) < 0) return IDL_RETCODE_NO_MEMORY; + // ostream cpp + static const char* fmt2 = " os << \"%1$s: \" << rhs.%1$s(); break;\n"; + if (idl_fprintf(gen->impl.handle, fmt2, branch_name) < 0) + return IDL_RETCODE_NO_MEMORY; + return IDL_RETCODE_OK; } @@ -1012,6 +1094,14 @@ emit_union( if (idl_fprintf(gen->header.handle, fmt, type, value) < 0) return IDL_RETCODE_NO_MEMORY; + // ostream cpp + fmt = "std::ostream& operator<<(std::ostream& os, %1$s const& rhs)\n" + "{\n" + " (void) rhs;\n" + " switch (rhs._d()) {\n"; + if (idl_fprintf(gen->impl.handle, fmt, name) < 0) + return IDL_RETCODE_NO_MEMORY; + visitor.visit = IDL_CASE | IDL_CASE_LABEL; visitor.accept[IDL_ACCEPT_CASE] = emit_case; visitor.accept[IDL_ACCEPT_CASE_LABEL] = emit_case_label; @@ -1076,17 +1166,25 @@ emit_union( if (idl_fprintf(gen->header.handle, fmt, name) < 0) return IDL_RETCODE_NO_MEMORY; + gen_ostream_case = true; visitor.visit = IDL_CASE | IDL_CASE_LABEL; visitor.accept[IDL_ACCEPT_CASE] = emit_case_comparison; visitor.accept[IDL_ACCEPT_CASE_LABEL] = emit_case_label; if ((ret = idl_visit(pstate, _union->cases, &visitor, user_data))) return ret; + gen_ostream_case = false; + if (gen_default) { fmt = " default:\n" " return true;\n"; if (idl_fprintf(gen->header.handle, fmt, name) < 0) return IDL_RETCODE_NO_MEMORY; + + fmt = " default:\n {\n" + " // Prevent compiler warnings\n }\n"; + if (idl_fprintf(gen->impl.handle, fmt, name) < 0) + return IDL_RETCODE_NO_MEMORY; } fmt = " }\n" @@ -1099,6 +1197,10 @@ emit_union( if (idl_fprintf(gen->header.handle, fmt, name) < 0) return IDL_RETCODE_NO_MEMORY; + // ostream cpp + if (idl_fprintf(gen->impl.handle, " }\n return os;\n}\n\n") < 0) + return IDL_RETCODE_NO_MEMORY; + /* implicit default setter */ if (idl_mask(_union->default_case) == IDL_IMPLICIT_DEFAULT_CASE_LABEL) { @@ -1116,6 +1218,12 @@ emit_union( if (fputs("};\n\n", gen->header.handle) < 0) return IDL_RETCODE_NO_MEMORY; + // ostream hpp + fmt = "std::ostream& operator<<(std::ostream& os, %s const& rhs);\n"; + if (idl_fprintf(gen->header.handle, fmt, name) < 0) + return IDL_RETCODE_NO_MEMORY; + + return IDL_RETCODE_OK; }