Verified Commit 97d1db7c authored by Daniel Vrátil's avatar Daniel Vrátil 🤖
Browse files

Use std::optional instead of akOptional

parent d30dd8b2
# Don't add Optional subdir, it has install() rules that we don't want
install(FILES Optional/optional.hpp DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/AkonadiCore/)
# if CMAKE_VERSION >= 3.0 this project installs an INTERFACE target for
# the optional.hpp file.
#
# Usage:
#
# In your project's CMakeLists.txt:
#
# find_package(akrzemi1_optional REQUIRED)
# ...
# target_link_libraries(mytarget ... akrzemi1::optional ...)
#
# In your C++ source file:
#
# #include "akrzemi1/optional.hpp"
#
project(optional)
cmake_minimum_required(VERSION 2.8)
enable_testing()
if(CMAKE_VERSION VERSION_LESS 3.1)
set(CMAKE_CXX_FLAGS "-std=c++11")
elseif(NOT CMAKE_CXX_STANDARD) # don't override c++ standard if already set
set(CMAKE_CXX_STANDARD 11)
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
# if CMAKE_VERSION >= 3.0
if(NOT (CMAKE_VERSION VERSION_LESS 3.0))
add_library(optional INTERFACE)
target_include_directories(optional INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<INSTALL_INTERFACE:include>)
install(TARGETS optional EXPORT optional-targets)
install(EXPORT optional-targets DESTINATION lib/cmake/akrzemi1_optional
FILE akrzemi1_optional-config.cmake
NAMESPACE akrzemi1::)
install(FILES optional.hpp DESTINATION include/akrzemi1)
endif()
add_executable(test_optional test_optional.cpp)
add_executable(test_type_traits test_type_traits.cpp)
add_test(test_optional test_optional)
add_test(test_type_traits test_type_traits)
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
Optional
========
A single-header header-only library for representing optional (nullable) objects for C++14 (and C++11 to some extent) and passing them by value. This is the reference implementation of proposal N3793 (see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3793.html). Optional is now accepted into Library Fundamentals Technical Specification (see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3848.html). The interface is based on Fernando Cacciola's Boost.Optional library (see http://www.boost.org/doc/libs/1_52_0/libs/optional/doc/html/index.html)
Usage
-----
```cpp
optional<int> readInt(); // this function may return int or a not-an-int
if (optional<int> oi = readInt()) // did I get a real int
cout << "my int is: " << *oi; // use my int
else
cout << "I have no int";
```
For more usage examples and the overview see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3527.html
Supported compilers
-------------------
Clang 3.2, Clang 3.4, G++ 4.7.2, G++ 4.8.1. Tested only with libstdc++, versions 20130531, 20120920, 20110428. Others have reported it also works with libc++.
Known Issues
------------
- Currently, the reference (and the only known) implementation of certain pieces of functionality explore what C++11 identifies as undefined behavior (see national body comment FI 15: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3770.html#FI15). This is mostly why Optional was removed from C++14 and put into Library Fundamentals TS. Luckily what the Standard identifies as UB is well defined on all known platforms. We expect that the C++14 wil fix this problem, so that our trick becomes well-defined.
- In libstdc++ versions below 20130531 the constructor taking `initializer_list` argument is not `constexpr`. This is because `initializer_list` operations are not `constexpr` in C++11. This works however in version 20130531. It is also not enabled for libc++ because I do not have access to it and do not know if it provides `constexpr` `initializer_list`.
- In G++ 4.7.2 and 4.8.0 member function `value_or` does not have rvalue reference overload. These compilers do not support rvalue overloding on `*this`.
- In order for the library to work with slightly older compilers, we emulate some missing type traits. On some platforms we cannot correctly detect the available features, and attempts at workarounds for missing type trait definitions can cause compile-time errors. Define macro `TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS` if you know that all the necessary type traits are defined, and no emulation is required.
License
-------
Distributed under the [Boost Software License, Version 1.0](http://www.boost.org/LICENSE_1_0.txt).
Copyright (C) 2011-2016 Andrzej Krzemienski
Distributed under the Boost Software License, Version 1.0
(see accompanying file LICENSE_1_0.txt or a copy at
http://www.boost.org/LICENSE_1_0.txt)
The idea and interface is based on Boost.Optional library
authored by Fernando Luis Cacciola Carballal
Home at https://github.com/akrzemi1/Optional
This diff is collapsed.
This diff is collapsed.
// Copyright (C) 2011 - 2012 Andrzej Krzemienski.
//
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#if (defined __clang__)
namespace std { class type_info; }
#endif
# include "optional.hpp"
namespace std { namespace experimental {
struct Val
{
Val(){}
Val( Val const & ){}
Val( Val && ) noexcept {}
Val & operator=( Val const & ) = delete;
Val & operator=( Val && ) noexcept = delete;
};
struct Safe
{
Safe(){}
Safe( Safe const & ){}
Safe( Safe && ) noexcept {}
Safe & operator=( Safe const & ){ return *this; }
Safe & operator=( Safe && ) noexcept { return *this; }
};
struct Unsafe
{
Unsafe(){}
Unsafe( Unsafe const & ){}
Unsafe( Unsafe && ){}
Unsafe & operator=( Unsafe const & ){ return *this; }
Unsafe & operator=( Unsafe && ) { return *this; }
};
struct VoidNothrowBoth
{
VoidNothrowBoth(VoidNothrowBoth&&) noexcept(true) {};
void operator=(VoidNothrowBoth&&) noexcept(true) {}; // note void return type
};
static_assert(is_nothrow_move_constructible<Safe>::value, "WTF!");
static_assert(!is_nothrow_move_constructible<Unsafe>::value, "WTF!");
static_assert(is_assignable<Safe&, Safe&&>::value, "WTF!");
static_assert(!is_assignable<Val&, Val&&>::value, "WTF!");
static_assert(is_nothrow_move_assignable<Safe>::value, "WTF!");
static_assert(!is_nothrow_move_assignable<Unsafe>::value, "WTF!");
static_assert(is_nothrow_move_constructible<VoidNothrowBoth>::value, "WTF!");
static_assert(is_nothrow_move_assignable<VoidNothrowBoth>::value, "WTF!");
}} // namespace std::experimental
int main() { }
add_subdirectory(3rdparty)
add_subdirectory(agentserver)
add_subdirectory(akonadicontrol)
add_subdirectory(akonadictl)
......
......@@ -54,7 +54,7 @@ bool AccountsIntegration::isEnabled() const
#endif
}
akOptional<quint32> AccountsIntegration::accountId() const
std::optional<quint32> AccountsIntegration::accountId() const
{
return mAccountId;
}
......@@ -67,23 +67,23 @@ quint32 AccountsIntegration::getAccountId() const
void AccountsIntegration::setAccountId(quint32 accountId)
{
if (accountId <= 0) {
mAccountId = nullopt;
mAccountId = std::nullopt;
} else {
mAccountId = accountId;
}
Q_EMIT accountChanged();
}
akOptional<QString> AccountsIntegration::accountName() const
std::optional<QString> AccountsIntegration::accountName() const
{
#ifdef WITH_ACCOUNTS
if (!mAccountId.has_value()) {
return nullopt;
return std::nullopt;
}
const auto account = KAccounts::accountsManager()->account(mAccountId.value());
if (!account) {
return nullopt;
return std::nullopt;
}
return account->displayName();
......
......@@ -22,9 +22,9 @@
#include <QObject>
#include "akonadiagentbase_export.h"
#include <akoptional.h>
#include <functional>
#include <optional>
class Akonadi__AccountsAdaptor;
namespace Akonadi
......@@ -48,19 +48,19 @@ public:
using ErrorCallback = std::function<void(const QString &)>;
void requestAuthData(const QString &serviceType, AuthDataCallback &&cb, ErrorCallback &&err);
akOptional<QString> accountName() const;
std::optional<QString> accountName() const;
public Q_SLOTS:
akOptional<quint32> accountId() const;
std::optional<quint32> accountId() const;
void setAccountId(quint32 accountId);
Q_SIGNALS:
void accountChanged();
private:
// For DBus adaptor which doesn't understand akOptional
// For DBus adaptor which doesn't understand std::optional
quint32 getAccountId() const;
akOptional<quint32> mAccountId;
std::optional<quint32> mAccountId;
};
......
......@@ -55,7 +55,7 @@ AccountsIntegration::AccountsIntegration(AgentManager &agentManager)
}
}
akOptional<QString> AccountsIntegration::agentForAccount(const QString &agentType, Accounts::AccountId accountId) const
std::optional<QString> AccountsIntegration::agentForAccount(const QString &agentType, Accounts::AccountId accountId) const
{
const auto instances = mAgentManager.agentInstances();
for (const auto &identifier : instances) {
......@@ -71,7 +71,7 @@ akOptional<QString> AccountsIntegration::agentForAccount(const QString &agentTyp
}
}
}
return nullopt;
return std::nullopt;
}
void AccountsIntegration::configureAgentInstance(const QString &identifier, Accounts::AccountId accountId, int attempt)
......
......@@ -25,7 +25,7 @@
#include <Accounts/Manager>
#include <shared/akoptional.h>
#include <optional>
namespace Accounts
{
......@@ -48,7 +48,7 @@ private Q_SLOTS:
private:
void configureAgentInstance(const QString &identifier, Accounts::AccountId accountId, int attempt = 0);
Akonadi::akOptional<QString> agentForAccount(const QString &agentType, Accounts::AccountId accountId) const;
std::optional<QString> agentForAccount(const QString &agentType, Accounts::AccountId accountId) const;
void createAgent(const QString &agentType, Accounts::AccountId accountId);
void removeAgentInstance(const QString &identifier);
void loadSupportedServices();
......
......@@ -650,7 +650,7 @@ void AgentManager::serviceOwnerChanged(const QString &name, const QString &oldOw
// Ignore services belonging to another Akonadi instance
const auto parsedInstance = Akonadi::DBus::parseInstanceIdentifier(name);
const auto currentInstance = Akonadi::Instance::hasIdentifier() ? Akonadi::akOptional<QString>(Akonadi::Instance::identifier()) : Akonadi::nullopt;
const auto currentInstance = Akonadi::Instance::hasIdentifier() ? std::optional<QString>(Akonadi::Instance::identifier()) : std::nullopt;
if (parsedInstance != currentInstance) {
return;
}
......
......@@ -49,7 +49,7 @@ ecm_qt_declare_logging_category(akonadiprivate_SRCS HEADER akonadiprivate_debug.
macro(update_include_directories _target)
target_include_directories(${_target} PUBLIC "$<BUILD_INTERFACE:${Akonadi_SOURCE_DIR}/src/private;${Akonadi_BINARY_DIR}/src/private;${Akonadi_BINARY_DIR}/src>")
target_include_directories(${_target} PRIVATE "$<BUILD_INTERFACE:${Akonadi_SOURCE_DIR}/src/3rdparty/Optional;${Akonadi_SOURCE_DIR}/src/shared>")
target_include_directories(${_target} PRIVATE "${Akonadi_SOURCE_DIR}/src/shared>")
target_include_directories(${_target} PUBLIC "$<BUILD_INTERFACE:${Qt5Core_INCLUDE_DIRS};${Qt5DBus_INCLUDE_DIRS}>")
endmacro()
......
......@@ -64,10 +64,10 @@ QString DBus::serviceName(DBus::ServiceType serviceType)
return QString();
}
akOptional<DBus::AgentService> DBus::parseAgentServiceName(const QString &serviceName)
std::optional<DBus::AgentService> DBus::parseAgentServiceName(const QString &serviceName)
{
if (!serviceName.startsWith(AKONADI_DBUS_SERVER_SERVICE ".")) {
return nullopt;
return std::nullopt;
}
const auto parts = serviceName.midRef(QStringView(AKONADI_DBUS_SERVER_SERVICE ".").length()).split(QLatin1Char('.'));
......@@ -81,11 +81,11 @@ akOptional<DBus::AgentService> DBus::parseAgentServiceName(const QString &servic
} else if (parts.at(0) == QLatin1String("Preprocessor")) {
return AgentService{parts.at(1).toString(), DBus::Preprocessor};
} else {
return nullopt;
return std::nullopt;
}
}
return nullopt;
return std::nullopt;
}
QString DBus::agentServiceName(const QString &agentIdentifier, DBus::AgentType agentType)
......@@ -113,7 +113,7 @@ QString DBus::agentServiceName(const QString &agentIdentifier, DBus::AgentType a
return serviceName;
}
akOptional<QString> DBus::parseInstanceIdentifier(const QString &serviceName)
std::optional<QString> DBus::parseInstanceIdentifier(const QString &serviceName)
{
constexpr std::array<QStringView, 5> services = {QStringView{AKONADI_DBUS_STORAGEJANITOR_SERVICE},
QStringView{AKONADI_DBUS_SERVER_SERVICE_UPGRADING},
......@@ -125,14 +125,14 @@ akOptional<QString> DBus::parseInstanceIdentifier(const QString &serviceName)
if (serviceName != service) {
return serviceName.mid(service.length() + 1); // +1 for the separator "."
}
return nullopt;
return std::nullopt;
}
}
if (serviceName.startsWith(QStringView{AKONADI_DBUS_SERVER_SERVICE})) {
const auto split = serviceName.splitRef(QLatin1Char('.'));
if (split.size() <= 3) {
return nullopt;
return std::nullopt;
}
// [0]org.[1]freedesktop.[2]Akonadi.[3]type.[4]identifier.[5]instance
......@@ -140,12 +140,12 @@ akOptional<QString> DBus::parseInstanceIdentifier(const QString &serviceName)
if (split.size() == 6) {
return split[5].toString();
} else {
return nullopt;
return std::nullopt;
}
} else {
return split[3].toString();
}
}
return nullopt;
return std::nullopt;
}
......@@ -24,7 +24,7 @@
#include <QString>
#include "akoptional.h"
#include <optional>
/**
* Helper methods for obtaining D-Bus identifiers.
......@@ -75,7 +75,7 @@ struct AgentService {
* @param serviceName The service name to parse.
* @return The identifier of the agent, empty string if that's not an agent (or an agent of a different Akonadi instance)
*/
AKONADIPRIVATE_EXPORT akOptional<AgentService> parseAgentServiceName(const QString &serviceName);
AKONADIPRIVATE_EXPORT std::optional<AgentService> parseAgentServiceName(const QString &serviceName);
/**
* Returns the D-Bus service name of the agent @p agentIdentifier for type @p agentType.
......@@ -85,7 +85,7 @@ AKONADIPRIVATE_EXPORT QString agentServiceName(const QString &agentIdentifier, D
/**
* Returns the Akonadi instance name encoded in the service name.
*/
AKONADIPRIVATE_EXPORT akOptional<QString> parseInstanceIdentifier(const QString &serviceName);
AKONADIPRIVATE_EXPORT std::optional<QString> parseInstanceIdentifier(const QString &serviceName);
}
......
......@@ -25,8 +25,6 @@
#include <memory>
#include <shared/akoptional.h>
class QProcess;
class QDBusServiceWatcher;
class QSettings;
......
......@@ -78,12 +78,12 @@ Collection CommandContext::collection() const
return mCollection;
}
void CommandContext::setTag(akOptional<qint64> tagId)
void CommandContext::setTag(std::optional<qint64> tagId)
{
mTagId = std::move(tagId);
}
akOptional<qint64> CommandContext::tagId() const
std::optional<qint64> CommandContext::tagId() const
{
return mTagId;
}
......
......@@ -22,7 +22,7 @@
#include "entities.h"
#include <shared/akoptional.h>
#include <optional>
namespace Akonadi
{
......@@ -47,8 +47,8 @@ public:
qint64 collectionId() const;
Collection collection() const;
void setTag(akOptional<qint64> tagId);
akOptional<qint64> tagId() const;
void setTag(std::optional<qint64> tagId);
std::optional<qint64> tagId() const;
Tag tag() const;
bool isEmpty() const;
......@@ -56,7 +56,7 @@ public:
private:
Resource mResource;
Collection mCollection;
akOptional<qint64> mTagId;
std::optional<qint64> mTagId;
};
}
......
......@@ -250,7 +250,7 @@ void Connection::handleIncomingData()
}
// Tag context and collection context is not persistent.
m_context.setTag(nullopt);
m_context.setTag(std::nullopt);
m_context.setCollection({});
if (m_akonadi.tracer().currentTracer() != QLatin1String("null")) {
m_akonadi.tracer().connectionInput(m_identifier, tag, cmd);
......
......@@ -22,7 +22,6 @@
#include "akonadiserver_debug.h"
#include <private/standarddirs_p.h>
#include <shared/akoptional.h>
#include <shared/akranges.h>
#include <QDir>
......@@ -39,6 +38,7 @@
#include <unistd.h>
#endif
#include <chrono>
#include <optional>
using namespace std::chrono_literals;
......@@ -85,7 +85,7 @@ private:
int major;
int minor;
};
akOptional<Version> parseVersion(const QString &name) const
std::optional<Version> parseVersion(const QString &name) const
{
const auto dotIdx = name.indexOf(QLatin1Char('.'));
if (dotIdx == -1) {
......@@ -245,19 +245,19 @@ bool DbConfigPostgresql::useInternalServer() const
return mInternalServer;
}
akOptional<DbConfigPostgresql::Versions> DbConfigPostgresql::checkPgVersion() const
std::optional<DbConfigPostgresql::Versions> DbConfigPostgresql::checkPgVersion() const
{
// Contains major version of Postgres that creted the cluster
QFile pgVersionFile(QStringLiteral("%1/PG_VERSION").arg(mPgData));
if (!pgVersionFile.open(QIODevice::ReadOnly)) {
return nullopt;
return std::nullopt;
}
const auto clusterVersion = pgVersionFile.readAll().toInt();
QProcess pgctl;
pgctl.start(mServerPath, { QStringLiteral("--version") }, QIODevice::ReadOnly);
if (!pgctl.waitForFinished()) {
return nullopt;
return std::nullopt;
}
// Looks like "pg_ctl (PostgreSQL) 11.2"
const auto output = QString::fromUtf8(pgctl.readAll());
......@@ -266,7 +266,7 @@ akOptional<DbConfigPostgresql::Versions> DbConfigPostgresql::checkPgVersion() co
QRegularExpression re(QStringLiteral("\\(PostgreSQL\\) ([0-9]+).[0-9]+"));
const auto match = re.match(output);
if (!match.hasMatch()) {
return nullopt;
return std::nullopt;
}
const auto serverVersion = match.captured(1).toInt();
......@@ -299,7 +299,7 @@ bool DbConfigPostgresql::runInitDb(const QString &newDbPath)
namespace {
akOptional<QString> findBinPathForVersion(int version)
std::optional<QString> findBinPathForVersion(int version)
{
// First we need to find where the previous PostgreSQL version binaries are available
const auto oldBinSearchPaths = {
......@@ -316,7 +316,7 @@ akOptional<QString> findBinPathForVersion(int version)
}
}
return nullopt;
return std::nullopt;
}
bool checkAndRemoveTmpCluster(const QDir &baseDir, const QString &clusterName)
......
......@@ -22,7 +22,7 @@
#include "dbconfig.h"
#include <shared/akoptional.h>
#include <optional>
namespace Akonadi
{
......@@ -82,7 +82,7 @@ private:
int clusterVersion = 0;
int pgServerVersion = 0;
};
akOptional<Versions> checkPgVersion() const;
std::optional<Versions> checkPgVersion() const;
bool upgradeCluster(int clusterVersion);
bool runInitDb(const QString &dbDataPath);
......