diff --git a/NEWS b/NEWS index 509b0be15..9c4ea5a62 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,8 @@ ver 0.22 (not yet released) - ffmpeg: new plugin based on FFmpeg's libavfilter library - hdcd: new plugin based on FFmpeg's "af_hdcd" for HDCD playback - volume: convert S16 to S24 to preserve quality and reduce dithering noise +* switch to C++17 + - GCC 7 or clang 4 (or newer) recommended ver 0.21.12 (2019/08/03) * decoder diff --git a/doc/developer.rst b/doc/developer.rst index 5296314f9..717e72ffc 100644 --- a/doc/developer.rst +++ b/doc/developer.rst @@ -12,7 +12,7 @@ Code Style * indent with tabs (width 8) * don't write CPP when you can write C++: use inline functions and constexpr instead of macros * comment your code, document your APIs -* the code should be C++14 compliant, and must compile with :program:`GCC` 6.0 and :program:`clang` 3.4 +* the code should be C++17 compliant, and must compile with :program:`GCC` 7 and :program:`clang` 4 * report error conditions with C++ exceptions, preferable derived from :envvar:`std::runtime_error` * all code must be exception-safe * classes and functions names use CamelCase; variables are lower-case with words separated by underscore diff --git a/meson.build b/meson.build index e3ec613cf..43be24840 100644 --- a/meson.build +++ b/meson.build @@ -5,7 +5,7 @@ project( meson_version: '>= 0.49.0', default_options: [ 'c_std=c99', - 'cpp_std=c++14' + 'cpp_std=c++17' ], license: 'GPLv2+', ) @@ -15,10 +15,10 @@ version_cxx = vcs_tag(input: 'src/GitVersion.cxx', output: 'GitVersion.cxx') compiler = meson.get_compiler('cpp') c_compiler = meson.get_compiler('c') -if compiler.get_id() == 'gcc' and compiler.version().version_compare('<6') - warning('Your GCC version is too old. You need at least version 6.') -elif compiler.get_id() == 'clang' and compiler.version().version_compare('<3') - warning('Your clang version is too old. You need at least version 3.') +if compiler.get_id() == 'gcc' and compiler.version().version_compare('<7') + warning('Your GCC version is too old. You need at least version 7.') +elif compiler.get_id() == 'clang' and compiler.version().version_compare('<4') + warning('Your clang version is too old. You need at least version 4.') endif conf = configuration_data() diff --git a/src/event/MaskMonitor.hxx b/src/event/MaskMonitor.hxx index 1f4d9f3da..4a95eb835 100644 --- a/src/event/MaskMonitor.hxx +++ b/src/event/MaskMonitor.hxx @@ -34,7 +34,7 @@ class MaskMonitor final { DeferEvent defer; - typedef BoundMethod Callback; + typedef BoundMethod Callback; const Callback callback; std::atomic_uint pending_mask; diff --git a/src/event/TimerEvent.hxx b/src/event/TimerEvent.hxx index dbc2f6cc7..885a84ee6 100644 --- a/src/event/TimerEvent.hxx +++ b/src/event/TimerEvent.hxx @@ -44,7 +44,7 @@ class TimerEvent final { EventLoop &loop; - typedef BoundMethod Callback; + typedef BoundMethod Callback; const Callback callback; /** diff --git a/src/lib/dbus/AsyncRequest.hxx b/src/lib/dbus/AsyncRequest.hxx index 1a5ae8c13..9450a3e7a 100644 --- a/src/lib/dbus/AsyncRequest.hxx +++ b/src/lib/dbus/AsyncRequest.hxx @@ -49,7 +49,7 @@ namespace ODBus { class AsyncRequest { PendingCall pending_call; - std::function callback; + std::function callback; public: operator bool() const noexcept { diff --git a/src/thread/Thread.hxx b/src/thread/Thread.hxx index 7cfe8f710..bcb385c36 100644 --- a/src/thread/Thread.hxx +++ b/src/thread/Thread.hxx @@ -32,7 +32,7 @@ #include class Thread { - typedef BoundMethod Function; + typedef BoundMethod Function; const Function f; #ifdef _WIN32 diff --git a/src/util/BindMethod.hxx b/src/util/BindMethod.hxx index f6928877a..81da8e874 100644 --- a/src/util/BindMethod.hxx +++ b/src/util/BindMethod.hxx @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016 Max Kellermann + * Copyright 2016-2018 Max Kellermann * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,6 +30,8 @@ #ifndef BIND_METHOD_HXX #define BIND_METHOD_HXX +#include "Compiler.h" + #include #include @@ -43,9 +45,21 @@ template class BoundMethod; -template -class BoundMethod { - typedef R (*function_pointer)(void *instance, Args... args); +#if GCC_OLDER_THAN(7,0) +static constexpr bool NoExcept = false; +#endif + +template +class BoundMethod { + typedef R (*function_pointer)(void *instance, Args... args) +#if !GCC_OLDER_THAN(7,0) + noexcept(NoExcept) +#endif + ; void *instance_; function_pointer function; @@ -91,9 +105,21 @@ namespace BindMethodDetail { template struct MethodWithSignature; -template -struct MethodWithSignature { - typedef R (T::*method_pointer)(Args...); +template +struct MethodWithSignature { + typedef R (T::*method_pointer)(Args...) +#if !GCC_OLDER_THAN(7,0) + noexcept(NoExcept) +#endif + ; }; /** @@ -104,8 +130,12 @@ struct MethodWithSignature { template struct MethodSignatureHelper; -template -struct MethodSignatureHelper { +template +struct MethodSignatureHelper { /** * The class which contains the given method (signature). */ @@ -115,7 +145,11 @@ struct MethodSignatureHelper { * A function type which describes the "plain" function * signature. */ - typedef R plain_signature(Args...); + typedef R plain_signature(Args...) +#if !GCC_OLDER_THAN(7,0) + noexcept(NoExcept) +#endif + ; }; /** @@ -125,9 +159,17 @@ struct MethodSignatureHelper { template struct MethodWrapperWithSignature; -template -struct MethodWrapperWithSignature { - typedef R (*function_pointer)(void *instance, Args...); +template +struct MethodWrapperWithSignature { + typedef R (*function_pointer)(void *instance, Args...) +#if !GCC_OLDER_THAN(7,0) + noexcept(NoExcept) +#endif + ; }; /** @@ -140,9 +182,9 @@ struct MethodWrapperWithSignature { * @param R the return type * @param Args the method arguments */ -template +template struct BindMethodWrapperGenerator2 { - static R Invoke(void *_instance, Args... args) { + static R Invoke(void *_instance, Args... args) noexcept(NoExcept) { auto &t = *(T *)_instance; return (t.*method)(std::forward(args)...); } @@ -159,9 +201,13 @@ struct BindMethodWrapperGenerator2 { template struct BindMethodWrapperGenerator; -template -struct BindMethodWrapperGenerator - : BindMethodWrapperGenerator2 { +template +struct BindMethodWrapperGenerator + : BindMethodWrapperGenerator2 { }; template struct FunctionTraits; -template -struct FunctionTraits { +template +struct FunctionTraits { /** * A function type which describes the "plain" function * signature. */ - typedef R function_type(Args...); + typedef R function_type(Args...) +#if !GCC_OLDER_THAN(7,0) + noexcept(NoExcept) +#endif + ; /** * A function pointer type which describes the "plain" * function signature. */ - typedef R (*pointer_type)(Args...); + typedef R (*pointer_type)(Args...) +#if !GCC_OLDER_THAN(7,0) + noexcept(NoExcept) +#endif + ; }; /** @@ -205,9 +263,9 @@ struct FunctionTraits { * @param R the return type * @param Args the function arguments */ -template +template struct BindFunctionWrapperGenerator2 { - static R Invoke(void *, Args... args) { + static R Invoke(void *, Args... args) noexcept(NoExcept) { return function(std::forward(args)...); } }; @@ -222,9 +280,13 @@ struct BindFunctionWrapperGenerator2 { template struct BindFunctionWrapperGenerator; -template -struct BindFunctionWrapperGenerator - : BindFunctionWrapperGenerator2 { +template +struct BindFunctionWrapperGenerator + : BindFunctionWrapperGenerator2 { }; template diff --git a/test/meson.build b/test/meson.build index 7b4325322..d426731ac 100644 --- a/test/meson.build +++ b/test/meson.build @@ -49,6 +49,8 @@ test('TestUtil', executable( test('TestRewindInputStream', executable( 'TestRewindInputStream', 'TestRewindInputStream.cxx', + '../src/Log.cxx', + '../src/LogBackend.cxx', include_directories: inc, dependencies: [ input_glue_dep,