Skip to content

Commit

Permalink
Backport of some concepts from util to C++17
Browse files Browse the repository at this point in the history
  • Loading branch information
gpicciuca committed Jan 31, 2025
1 parent f2562fe commit e50ec72
Show file tree
Hide file tree
Showing 26 changed files with 543 additions and 359 deletions.
16 changes: 8 additions & 8 deletions benchmark/BenchmarkExamples.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,14 @@ class ConfigOptions : public BenchmarkInterface {

manager.addOption("date", "The current date.", &dateString_, "22.3.2023"s);

auto numSigns =
manager.addOption("num-signs", "The number of street signs.",
&numberOfStreetSigns_, 10000);
manager.addValidator([](const int& num) { return num >= 0; },
"The number of street signs must be at least 0!",
"Negative numbers, or floating point numbers, are not "
"allowed for the configuration option \"num-signs\".",
numSigns);
// auto numSigns =
// manager.addOption("num-signs", "The number of street signs.",
// &numberOfStreetSigns_, 10000);
// manager.addValidator([](const int& num) -> bool { return num >= 0; },
// "The number of street signs must be at least 0!",
// "Negative numbers, or floating point numbers, are not "
// "allowed for the configuration option \"num-signs\".",
// numSigns);

manager.addOption("coin-flip-try", "The number of successful coin flips.",
&wonOnTryX_, {false, false, false, false, false});
Expand Down
4 changes: 2 additions & 2 deletions benchmark/infrastructure/BenchmarkMeasurementContainer.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,8 +227,8 @@ class ResultTable : public BenchmarkMetadataGetter {
@param row, column Which table entry to read. Starts with `(0,0)`.
*/
template <ad_utility::SameAsAnyTypeIn<EntryType> T>
T getEntry(const size_t row, const size_t column) const {
CPP_template(typename T)(requires ad_utility::SameAsAnyTypeIn<T, EntryType>) T
getEntry(const size_t row, const size_t column) const {
AD_CONTRACT_CHECK(row < numRows() && column < numColumns());
static_assert(!ad_utility::isSimilar<T, std::monostate>);

Expand Down
12 changes: 6 additions & 6 deletions benchmark/infrastructure/BenchmarkToJson.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ provided translation function for the vector entries.
@tparam TranslationFunction Has to be a function, that takes `VectorType`
and returns a `nlohmann:json` object.
*/
template <typename VectorType, ad_utility::InvocableWithExactReturnType<
nlohmann::ordered_json, VectorType>
TranslationFunction>
static nlohmann::json transformIntoJsonArray(
const std::vector<VectorType>& vec,
TranslationFunction translationFunction) {
CPP_template(typename VectorType, typename TranslationFunction)(
requires ad_utility::InvocableWithExactReturnType<
TranslationFunction, nlohmann::ordered_json,
VectorType>) static nlohmann::json
transformIntoJsonArray(const std::vector<VectorType>& vec,
TranslationFunction translationFunction) {
/*
Without explicit instantiation, `nlohmann::nlohmann::ordered_json` is not
guaranteed, to always interpret a `push_back` correctly. For instance,
Expand Down
6 changes: 4 additions & 2 deletions src/engine/idTable/IdTableRow.h
Original file line number Diff line number Diff line change
Expand Up @@ -381,8 +381,10 @@ class RowReference
// The `cbegin` and `cend` functions are implicitly inherited from `Base`.

// __________________________________________________________________________
template <ad_utility::SimilarTo<RowReference> R>
friend void swap(R&& a, R&& b) requires(!isConst) {
CPP_template(typename R)(
requires ad_utility::SimilarTo<RowReference, R>) friend void swap(R&& a,
R&& b)
requires(!isConst) {
return Base::swapImpl(AD_FWD(a), AD_FWD(b));
}

Expand Down
28 changes: 24 additions & 4 deletions src/global/Pattern.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <vector>

#include "global/Id.h"
#include "backports/concepts.h"
#include "util/ExceptionHandling.h"
#include "util/File.h"
#include "util/Generator.h"
Expand Down Expand Up @@ -71,6 +72,27 @@ struct CompactStringVectorWriter;

}

#ifdef QLEVER_CPP_17
template <typename T, typename = void>
struct IsIteratorOfIterator : std::false_type {};

template <typename T>
struct IsIteratorOfIterator<
T, std::void_t<decltype(*(T::iterator::value_type::begin()))>>
: std::true_type {};

template <typename T, typename DataType>
CPP_concept IteratorOfIterator =
(IsIteratorOfIterator<T>::value &&
ad_utility::SimilarTo<decltype(*(T::iterator::value_type::begin())),
DataType>);
#else
template <typename T, typename DataType>
concept IteratorOfIterator = requires(T t) {
{ *(t.begin()->begin()) } -> ad_utility::SimilarTo<DataType>;
};
#endif

/**
* @brief Stores a list of variable length data of a single type (e.g.
* c-style strings). The data is stored in a single contiguous block
Expand Down Expand Up @@ -102,10 +124,8 @@ class CompactVectorOfStrings {
* @brief Fills this CompactVectorOfStrings with input.
* @param The input from which to build the vector.
*/
template <typename T>
requires requires(T t) {
{ *(t.begin()->begin()) } -> ad_utility::SimilarTo<data_type>;
} void build(const T& input) {
CPP_template(typename T)(
requires IteratorOfIterator<T, data_type>) void build(const T& input) {
// Also make room for the end offset of the last element.
_offsets.reserve(input.size() + 1);
size_t dataSize = 0;
Expand Down
4 changes: 2 additions & 2 deletions src/index/StringSortComparator.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ class LocaleManager {
using U8String = std::basic_string<uint8_t>;
using U8StringView = std::basic_string_view<uint8_t>;

template <ad_utility::SimilarToAny<U8String, U8StringView> T>
class SortKeyImpl {
CPP_template(typename T)(requires ad_utility::SimilarToAny<
T, U8String, U8StringView>) class SortKeyImpl {
public:
SortKeyImpl() = default;
explicit SortKeyImpl(U8StringView sortKey) : sortKey_(sortKey) {}
Expand Down
6 changes: 4 additions & 2 deletions src/util/Algorithm.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,10 @@ bool contains_if(const Container& container, const Predicate& predicate) {
* @param destination Vector& to which to append
* @param source Vector&& to append
*/
template <typename T, ad_utility::SimilarTo<std::vector<T>> U>
void appendVector(std::vector<T>& destination, U&& source) {
CPP_template(typename T, typename U)(
requires ad_utility::SimilarTo<
std::vector<T>, U>) void appendVector(std::vector<T>& destination,
U&& source) {
destination.insert(destination.end(),
ad_utility::makeForwardingIterator<U>(source.begin()),
ad_utility::makeForwardingIterator<U>(source.end()));
Expand Down
31 changes: 18 additions & 13 deletions src/util/CancellationHandle.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
// Chair of Algorithms and Data Structures.
// Author: Robin Textor-Falconi <[email protected]>

#ifndef QLEVER_CANCELLATIONHANDLE_H
#define QLEVER_CANCELLATIONHANDLE_H
#ifndef SRC_UTIL_CANCELLATION_HANDLE_H
#define SRC_UTIL_CANCELLATION_HANDLE_H

#include <absl/strings/str_cat.h>
#include <gtest/gtest_prod.h>
Expand Down Expand Up @@ -156,10 +156,14 @@ class CancellationHandle {
/// in the console that would otherwise be triggered by the watchdog.
/// NOTE: The parameter state is expected to be one of `CHECK_WINDOW_MISSED`
/// or `WAITING_FOR_CHECK`, otherwise it will violate the correctness check.
void pleaseWatchDog(CancellationState state,
ad_utility::source_location location,
const ad_utility::InvocableWithConvertibleReturnType<
std::string_view> auto& stageInvocable)
CPP_template(typename StateFunc)(
requires ad_utility::InvocableWithConvertibleReturnType<
StateFunc,
std::string_view>) void pleaseWatchDog(CancellationState state,
ad_utility::source_location
location,
const StateFunc&
stageInvocable)
requires WatchDogEnabled {
using DurationType =
std::remove_const_t<decltype(DESIRED_CANCELLATION_CHECK_INTERVAL)>;
Expand Down Expand Up @@ -215,12 +219,13 @@ class CancellationHandle {
/// nothing otherwise. If `WatchDogEnabled` is true, this will log a warning
/// if this check is not called frequently enough. It will contain the
/// filename and line of the caller of this method.
template <ad_utility::InvocableWithConvertibleReturnType<std::string_view>
Func = decltype(detail::printNothing)>
AD_ALWAYS_INLINE void throwIfCancelled(
[[maybe_unused]] ad_utility::source_location location =
ad_utility::source_location::current(),
const Func& stageInvocable = detail::printNothing) {
CPP_template(typename Func = decltype(detail::printNothing))(
requires ad_utility::InvocableWithConvertibleReturnType<Func,
std::string_view>)
AD_ALWAYS_INLINE void throwIfCancelled(
[[maybe_unused]] ad_utility::source_location location =
ad_utility::source_location::current(),
const Func& stageInvocable = detail::printNothing) {
if constexpr (CancellationEnabled) {
auto state = cancellationState_.load(std::memory_order_relaxed);
if (state == CancellationState::NOT_CANCELLED) [[likely]] {
Expand Down Expand Up @@ -296,4 +301,4 @@ class CancellationHandle {
using SharedCancellationHandle = std::shared_ptr<CancellationHandle<>>;
} // namespace ad_utility

#endif // QLEVER_CANCELLATIONHANDLE_H
#endif // SRC_UTIL_CANCELLATION_HANDLE_H
124 changes: 67 additions & 57 deletions src/util/ConfigManager/ConfigManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,10 @@ ConfigManager::HashMapEntry::HashMapEntry(Data&& data)
: data_{std::make_unique<Data>(std::move(data))} {}

// ____________________________________________________________________________
template <SameAsAnyTypeIn<ConfigManager::HashMapEntry::Data> T>
bool ConfigManager::HashMapEntry::implHolds() const {
CPP_template_def(typename T)(
requires SameAsAnyTypeIn<
T, ConfigManager::HashMapEntry::Data>) bool ConfigManager::
HashMapEntry::implHolds() const {
// Make sure, that it is not a null pointer.
AD_CORRECTNESS_CHECK(data_);

Expand All @@ -64,10 +66,13 @@ bool ConfigManager::HashMapEntry::holdsSubManager() const {
}

// ____________________________________________________________________________
template <SimilarToAnyTypeIn<ConfigManager::HashMapEntry::Data> ReturnType>
requires std::is_object_v<ReturnType> std::optional<ReturnType*>
ConfigManager::HashMapEntry::getConfigOptionOrSubManager(
ad_utility::SimilarTo<ConfigManager::HashMapEntry> auto& instance) {
CPP_template_def(typename ReturnType, typename InstanceType)(
requires SimilarToAnyTypeIn<ReturnType, ConfigManager::HashMapEntry::Data>
CPP_and std::is_object_v<ReturnType>
CPP_and ad_utility::SimilarTo<ConfigManager::HashMapEntry,
InstanceType>)
std::optional<ReturnType*> ConfigManager::HashMapEntry::
getConfigOptionOrSubManager(InstanceType& instance) {
using DecayReturnType = std::decay_t<ReturnType>;
/*
We cheat a bit, by using `implHolds`, because so we can reduce the amount
Expand Down Expand Up @@ -104,32 +109,31 @@ std::optional<const ConfigManager*> ConfigManager::HashMapEntry::getSubManager()
}

// ____________________________________________________________________________
template <typename Visitor>
requires std::invocable<Visitor, ConfigOption&> &&
std::invocable<Visitor, ConfigManager&>
decltype(auto) ConfigManager::HashMapEntry::visit(Visitor&& vis) {
CPP_template_def(typename Visitor)(
requires std::invocable<Visitor, ConfigOption&> CPP_and
std::invocable<Visitor, ConfigManager&>) decltype(auto)
ConfigManager::HashMapEntry::visit(Visitor&& vis) {
return visitImpl(AD_FWD(vis), data_);
}
template <typename Visitor>
requires std::invocable<Visitor, const ConfigOption&> &&
std::invocable<Visitor, const ConfigManager&>
decltype(auto) ConfigManager::HashMapEntry::visit(Visitor&& vis) const {
CPP_template_def(typename Visitor)(
requires std::invocable<Visitor, ConfigOption&> CPP_and
std::invocable<Visitor, ConfigManager&>) decltype(auto)
ConfigManager::HashMapEntry::visit(Visitor&& vis) const {
return visitImpl(AD_FWD(vis), data_);
}

// ____________________________________________________________________________
template <
typename Visitor,
ad_utility::SimilarTo<std::unique_ptr<ConfigManager::HashMapEntry::Data>>
PointerType>
requires std::invocable<
Visitor, std::conditional_t<std::is_const_v<PointerType>,
const ConfigOption&, ConfigOption&>> &&
std::invocable<
Visitor, std::conditional_t<std::is_const_v<PointerType>,
const ConfigManager&, ConfigManager&>>
decltype(auto) ConfigManager::HashMapEntry::visitImpl(Visitor&& vis,
PointerType& data) {
CPP_template_def(typename Visitor, typename PointerType)(
requires ad_utility::SimilarTo<
std::unique_ptr<ConfigManager::HashMapEntry::Data>, PointerType>
CPP_and std::invocable<
Visitor, std::conditional_t<std::is_const_v<PointerType>,
const ConfigOption&, ConfigOption&>>
CPP_and std::invocable<
Visitor, std::conditional_t<std::is_const_v<PointerType>,
const ConfigManager&,
ConfigManager&>>) decltype(auto)
ConfigManager::HashMapEntry::visitImpl(Visitor&& vis, PointerType& data) {
// Make sure, that it is not a null pointer.
AD_CORRECTNESS_CHECK(data);

Expand All @@ -150,13 +154,14 @@ void ConfigManager::verifyHashMapEntry(std::string_view jsonPathToEntry,
}

// ____________________________________________________________________________
template <typename Visitor>
requires ad_utility::InvocableWithExactReturnType<
Visitor, void, std::string_view, ConfigManager&> &&
ad_utility::InvocableWithExactReturnType<
Visitor, void, std::string_view, ConfigOption&>
void ConfigManager::visitHashMapEntries(Visitor&& vis, bool sortByCreationOrder,
std::string_view pathPrefix) const {
CPP_template_def(typename Visitor)(
requires ad_utility::InvocableWithExactReturnType<
Visitor, void, std::string_view, ConfigManager&>
CPP_and ad_utility::InvocableWithExactReturnType<
Visitor, void, std::string_view,
ConfigOption&>) void ConfigManager::
visitHashMapEntries(Visitor&& vis, bool sortByCreationOrder,
std::string_view pathPrefix) const {
// For less code duplication.
using Pair = decltype(configurationOptions_)::value_type;

Expand Down Expand Up @@ -188,17 +193,18 @@ void ConfigManager::visitHashMapEntries(Visitor&& vis, bool sortByCreationOrder,
}

// ____________________________________________________________________________
template <
SimilarTo<ad_utility::HashMap<std::string, ConfigManager::HashMapEntry>>
CPP_template_def(typename HashMapType, typename Callable)(
requires SimilarTo<
ad_utility::HashMap<std::string, ConfigManager::HashMapEntry>,
HashMapType>
requires std::is_object_v<HashMapType> auto ConfigManager::allHashMapEntries(
HashMapType& hashMap, std::string_view pathPrefix,
const ad_utility::InvocableWithSimilarReturnType<
bool, const HashMapEntry&> auto& predicate)
-> std::conditional_t<
std::is_const_v<HashMapType>,
const std::vector<std::pair<const std::string, const HashMapEntry&>>,
std::vector<std::pair<std::string, HashMapEntry&>>> {
CPP_and std::is_object_v<HashMapType>) auto ConfigManager::
allHashMapEntries(HashMapType& hashMap, std::string_view pathPrefix,
const Callable& predicate)
-> std::conditional_t<
std::is_const_v<HashMapType>,
const std::vector<
std::pair<const std::string, const HashMapEntry&>>,
std::vector<std::pair<std::string, HashMapEntry&>>> {
std::conditional_t<
std::is_const_v<HashMapType>,
std::vector<std::pair<const std::string, const HashMapEntry&>>,
Expand Down Expand Up @@ -255,12 +261,13 @@ requires std::is_object_v<HashMapType> auto ConfigManager::allHashMapEntries(
}

// ____________________________________________________________________________
template <QL_CONCEPT_OR_TYPENAME(SameAsAny<ConfigOption&, const ConfigOption&>)
ReturnReference>
std::vector<std::pair<std::string, ReturnReference>>
ConfigManager::configurationOptionsImpl(
SimilarTo<ad_utility::HashMap<std::string, HashMapEntry>> auto&
configurationOptions) {
CPP_template_def(typename ConfigOptions, typename ReturnReference)(
requires SameAsAny<ReturnReference, ConfigOption&, const ConfigOption&>
CPP_and SimilarTo<
ad_utility::HashMap<std::string, ConfigManager::HashMapEntry>,
ConfigOptions>)
std::vector<std::pair<std::string, ReturnReference>> ConfigManager::
configurationOptionsImpl(ConfigOptions& configurationOptions) {
return ad_utility::transform(
allHashMapEntries(
configurationOptions, "",
Expand All @@ -274,13 +281,15 @@ ConfigManager::configurationOptionsImpl(
// ____________________________________________________________________________
std::vector<std::pair<std::string, ConfigOption&>>
ConfigManager::configurationOptions() {
return configurationOptionsImpl<ConfigOption&>(configurationOptions_);
return configurationOptionsImpl<decltype(configurationOptions_),
ConfigOption&>(configurationOptions_);
}

// ____________________________________________________________________________
std::vector<std::pair<std::string, const ConfigOption&>>
ConfigManager::configurationOptions() const {
return configurationOptionsImpl<const ConfigOption&>(configurationOptions_);
return configurationOptionsImpl<const decltype(configurationOptions_),
const ConfigOption&>(configurationOptions_);
}

// ____________________________________________________________________________
Expand Down Expand Up @@ -857,9 +866,10 @@ bool ConfigManager::containsOption(const ConfigOption& opt) const {
}

// ____________________________________________________________________________
template <QL_CONCEPT_OR_TYPENAME(ConfigOptionOrManager) T>
void ConfigManager::ConfigurationDocValidatorAssignment::addEntryUnderKey(
const T& key, const ConfigOptionValidatorManager& manager) {
CPP_template_def(typename T)(
requires ConfigOptionOrManager<T>) void ConfigManager::
ConfigurationDocValidatorAssignment::addEntryUnderKey(
const T& key, const ConfigOptionValidatorManager& manager) {
getHashMapBasedOnType<T>()[&key].push_back(&manager);
}
// Explicit instantiation for `ConfigOption` and `ConfigManager`.
Expand All @@ -871,9 +881,9 @@ template void ConfigManager::ConfigurationDocValidatorAssignment::
const ConfigOptionValidatorManager&);

// ____________________________________________________________________________
template <QL_CONCEPT_OR_TYPENAME(ConfigOptionOrManager) T>
auto ConfigManager::ConfigurationDocValidatorAssignment::getEntriesUnderKey(
const T& key) const -> ValueGetterReturnType {
CPP_template(typename T)(requires ConfigOptionOrManager<T>) auto ConfigManager::
ConfigurationDocValidatorAssignment::getEntriesUnderKey(const T& key) const
-> ValueGetterReturnType {
// The concerned hash map.
const MemoryAdressHashMap<T>& hashMap{getHashMapBasedOnType<T>()};

Expand Down
Loading

0 comments on commit e50ec72

Please sign in to comment.