Skip to content

Commit

Permalink
Merge branch 'ad-freiburg:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
Flixtastic authored Dec 25, 2024
2 parents 38425dc + 97c195a commit 3b83918
Show file tree
Hide file tree
Showing 16 changed files with 101 additions and 62 deletions.
3 changes: 2 additions & 1 deletion benchmark/JoinAlgorithmBenchmark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1328,7 +1328,8 @@ class GeneralInterfaceImplementation : public BenchmarkInterface {
*/
bool addNewRowToBenchmarkTable(
ResultTable* table,
const ad_utility::SameAsAny<float, size_t> auto changingParameterValue,
const QL_CONCEPT_OR_NOTHING(
ad_utility::SameAsAny<float, size_t>) auto changingParameterValue,
ad_utility::InvocableWithExactReturnType<bool, float, size_t, size_t,
size_t, size_t, float,
float> auto stopFunction,
Expand Down
5 changes: 3 additions & 2 deletions benchmark/infrastructure/Benchmark.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

#include "../benchmark/infrastructure/BenchmarkMeasurementContainer.h"
#include "../benchmark/infrastructure/BenchmarkMetadata.h"
#include "backports/concepts.h"
#include "util/ConfigManager/ConfigManager.h"
#include "util/CopyableUniquePtr.h"
#include "util/Exception.h"
Expand Down Expand Up @@ -67,8 +68,8 @@ class BenchmarkResults {
@param constructorArgs Arguments to pass to the constructor of the object,
that the new `CopyableUniquePtr` will own.
*/
template <
ad_utility::SameAsAny<ResultTable, ResultEntry, ResultGroup> EntryType>
template <QL_CONCEPT_OR_TYPENAME(
ad_utility::SameAsAny<ResultTable, ResultEntry, ResultGroup>) EntryType>
static EntryType& addEntryToContainerVector(
PointerVector<EntryType>& targetVector, auto&&... constructorArgs) {
targetVector.push_back(ad_utility::make_copyable_unique<EntryType>(
Expand Down
2 changes: 1 addition & 1 deletion benchmark/infrastructure/BenchmarkMeasurementContainer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ std::ostream& operator<<(std::ostream& os, const ResultGroup& resultGroup) {
}

// ____________________________________________________________________________
template <ad_utility::SameAsAny<ResultEntry, ResultTable> T>
template <typename T>
void ResultGroup::deleteEntryImpl(T& entry) {
// The vector, that holds our entries.
auto& vec = [this]() -> auto& {
Expand Down
2 changes: 1 addition & 1 deletion benchmark/infrastructure/BenchmarkMeasurementContainer.h
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ class ResultGroup : public BenchmarkMetadataGetter {

private:
// The implementation for the general deletion of entries.
template <ad_utility::SameAsAny<ResultEntry, ResultTable> T>
template <typename T>
void deleteEntryImpl(T& entry);
};

Expand Down
13 changes: 2 additions & 11 deletions src/backports/algorithm.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#include <range/v3/all.hpp>
#include <utility>

#include "backports/concepts.h"

// The following defines namespaces `ql::ranges` and `ql::views` that are almost
// drop-in replacements for `std::ranges` and `std::views`. In C++20 mode (when
// the `QLEVER_CPP_17` macro is not used), these namespaces are simply aliases
Expand All @@ -19,7 +21,6 @@
// currently not aware of, because they only affect functions that we currently
// don't use. For those, the following header can be expanded in the future.
#ifndef QLEVER_CPP_17
#include <concepts>
#include <ranges>
#endif

Expand All @@ -46,14 +47,4 @@ using namespace std::views;
#endif
} // namespace views

// The namespace `ql::concepts` includes concepts that are contained in the
// C++20 standard as well as in `range-v3`.
namespace concepts {
#ifdef QLEVER_CPP_17
using namespace ::concepts;
#else
using namespace std;
#endif
} // namespace concepts

} // namespace ql
58 changes: 48 additions & 10 deletions src/backports/concepts.h
Original file line number Diff line number Diff line change
@@ -1,17 +1,55 @@
// Copyright 2024, University of Freiburg,
// Chair of Algorithms and Data Structures.
// Author: Johannes Kalmbach <[email protected]>
// Copyright 2024, University of Freiburg
// Chair of Algorithms and Data Structures
// Author: Johannes Kalmbach <[email protected]>

#pragma once

#include <concepts/concepts.hpp>
#ifndef QLEVER_CPP_17
#include <concepts>
#endif

// Define the following macros:
// `QL_OPT_CONCEPT(arg)` which expands to `arg` in C++20 mode, and to nothing in
// C++17 mode. It can be used to easily opt out of concepts that are only used
// for documentation and increased safety and not for overload resolution.
// Example usage:
// `(QL_OPT_CONCEPT(std::view) auto x = someFunction();`
//
// `QL_CONCEPT_OR_NOTHING(arg)`: expands to `arg` in C++20 mode, and to
// nothing in C++17 mode. It can be used to easily opt out of concepts that are
// only used for documentation and increased safety and not for overload
// resolution.
//
// `QL_CONCEPT_OR_TYPENAME(arg)`: expands to `arg` in C++20 mode, and to
// `typename` in C++17 mode. Example usage:
//
// Example usages:
//
// `QL_CONCEPT_OR_NOTHING(std::view) auto x = someFunction();`
//
// `QL_CONCEPT_OR_NOTHING(SameAsAny<int, float>)`
//
// `void f(QL_CONCEPT_OR_NOTHING(std::view) auto x) {...}`
//
// `template <QL_CONCEPT_OR_TYPENAME(ql::same_as<int>) T> void f(){...}`
//
// NOTE: The macros are variadic to allow for commas in the argument, like in
// the second example above.

#ifdef QLEVER_CPP_17
#define QL_OPT_CONCEPT(arg)
#define QL_CONCEPT_OR_NOTHING(...)
#define QL_CONCEPT_OR_TYPENAME(...) typename
#else
#define QL_OPT_CONCEPT(arg) arg
#define QL_CONCEPT_OR_NOTHING(...) __VA_ARGS__
#define QL_CONCEPT_OR_TYPENAME(...) __VA_ARGS__
#endif

// The namespace `ql::concepts` includes concepts that are contained in the
// C++20 standard as well as in `range-v3`.
namespace ql {
namespace concepts {

#ifdef QLEVER_CPP_17
using namespace ::concepts;
#else
using namespace std;
#endif

} // namespace concepts
} // namespace ql
9 changes: 4 additions & 5 deletions src/engine/sparqlExpressions/LiteralExpression.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,10 @@ class LiteralExpression : public SparqlExpression {
// Evaluating just returns the constant/literal value.
ExpressionResult evaluate(EvaluationContext* context) const override {
// Common code for the `Literal` and `Iri` case.
auto getIdOrString =
[this,
&context](const ad_utility::SameAsAny<TripleComponent::Literal,
TripleComponent::Iri> auto& s)
-> ExpressionResult {
auto getIdOrString = [this, &context]<typename U>(const U& s)
-> CPP_ret(ExpressionResult)(
requires ad_utility::SameAsAny<U, TripleComponent::Literal,
TripleComponent::Iri>) {
if (auto ptr = cachedResult_.load(std::memory_order_relaxed)) {
return *ptr;
}
Expand Down
8 changes: 5 additions & 3 deletions src/util/ConfigManager/ConfigManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <variant>

#include "backports/algorithm.h"
#include "backports/concepts.h"
#include "util/Algorithm.h"
#include "util/ComparisonWithNan.h"
#include "util/ConfigManager/ConfigExceptions.h"
Expand Down Expand Up @@ -254,7 +255,8 @@ requires std::is_object_v<HashMapType> auto ConfigManager::allHashMapEntries(
}

// ____________________________________________________________________________
template <SameAsAny<ConfigOption&, const ConfigOption&> ReturnReference>
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&
Expand Down Expand Up @@ -855,7 +857,7 @@ bool ConfigManager::containsOption(const ConfigOption& opt) const {
}

// ____________________________________________________________________________
template <ConfigOptionOrManager T>
template <QL_CONCEPT_OR_TYPENAME(ConfigOptionOrManager) T>
void ConfigManager::ConfigurationDocValidatorAssignment::addEntryUnderKey(
const T& key, const ConfigOptionValidatorManager& manager) {
getHashMapBasedOnType<T>()[&key].push_back(&manager);
Expand All @@ -869,7 +871,7 @@ template void ConfigManager::ConfigurationDocValidatorAssignment::
const ConfigOptionValidatorManager&);

// ____________________________________________________________________________
template <ConfigOptionOrManager T>
template <QL_CONCEPT_OR_TYPENAME(ConfigOptionOrManager) T>
auto ConfigManager::ConfigurationDocValidatorAssignment::getEntriesUnderKey(
const T& key) const -> ValueGetterReturnType {
// The concerned hash map.
Expand Down
14 changes: 8 additions & 6 deletions src/util/ConfigManager/ConfigManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <variant>
#include <vector>

#include "backports/concepts.h"
#include "util/ConfigManager/ConfigExceptions.h"
#include "util/ConfigManager/ConfigOption.h"
#include "util/ConfigManager/ConfigOptionProxy.h"
Expand All @@ -34,7 +35,7 @@ namespace ConfigManagerImpl {
// Shorthand concepts, to reduce code duplication.
class ConfigManager;
template <typename T>
concept ConfigOptionOrManager = SameAsAny<T, ConfigOption, ConfigManager>;
CPP_concept ConfigOptionOrManager = SameAsAny<T, ConfigOption, ConfigManager>;

/*
Manages a bunch of `ConfigOption`s.
Expand Down Expand Up @@ -579,7 +580,8 @@ class ConfigManager {
@tparam ReturnReference Should be either `ConfigOption&`, or `const
ConfigOption&`.
*/
template <SameAsAny<ConfigOption&, const ConfigOption&> ReturnReference>
template <QL_CONCEPT_OR_TYPENAME(
SameAsAny<ConfigOption&, const ConfigOption&>) ReturnReference>
static std::vector<std::pair<std::string, ReturnReference>>
configurationOptionsImpl(
SimilarTo<ad_utility::HashMap<std::string, HashMapEntry>> auto&
Expand Down Expand Up @@ -716,7 +718,7 @@ class ConfigManager {
@brief Add a validator to the list of validators, that are assigned to a
`ConfigOption`/`ConfigManager`.
*/
template <ConfigOptionOrManager T>
template <QL_CONCEPT_OR_TYPENAME(ConfigOptionOrManager) T>
void addEntryUnderKey(const T& key,
const ConfigOptionValidatorManager& manager);

Expand All @@ -726,20 +728,20 @@ class ConfigManager {
@returns If there is no entry for `Key`, return an empty `std::vector`.
*/
template <ConfigOptionOrManager T>
template <QL_CONCEPT_OR_TYPENAME(ConfigOptionOrManager) T>
ValueGetterReturnType getEntriesUnderKey(const T& key) const;

private:
// Return either `configOption_` or `configManager_`, based on type.
template <ConfigOptionOrManager T>
template <QL_CONCEPT_OR_TYPENAME(ConfigOptionOrManager) T>
constexpr const MemoryAdressHashMap<T>& getHashMapBasedOnType() const {
if constexpr (std::same_as<T, ConfigOption>) {
return configOption_;
} else if constexpr (std::same_as<T, ConfigManager>) {
return configManager_;
}
}
template <ConfigOptionOrManager T>
template <QL_CONCEPT_OR_TYPENAME(ConfigOptionOrManager) T>
constexpr MemoryAdressHashMap<T>& getHashMapBasedOnType() {
if constexpr (std::same_as<T, ConfigOption>) {
return configOption_;
Expand Down
8 changes: 4 additions & 4 deletions src/util/ConfigManager/ConfigOptionProxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ access to the referenced config option.
@tparam ConfigOptionType The kind of config option, this proxy will reference
to. Must be `ConfigOption`, or `const ConfigOption`.
*/
template <
SupportedConfigOptionType T,
ad_utility::SameAsAny<ConfigOption, const ConfigOption> ConfigOptionType>
class ConfigOptionProxyImplementation {
CPP_template(typename T, typename ConfigOptionType)(
requires SupportedConfigOptionType<T> CPP_and ad_utility::SameAsAny<
ConfigOptionType, ConfigOption,
const ConfigOption>) class ConfigOptionProxyImplementation {
ConfigOptionType* option_;

public:
Expand Down
17 changes: 11 additions & 6 deletions src/util/FsstCompressor.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <string>
#include <vector>

#include "util/Concepts.h"
#include "util/Exception.h"
#include "util/Log.h"
#include "util/TypeTraits.h"
Expand All @@ -22,12 +23,16 @@ namespace detail {
// `const unsigned char*` which is used below because FSST always works on
// unsigned character types. Note that this is one of the few cases where a
// `reinterpret_cast` is safe.
constexpr auto castToUnsignedPtr =
[]<ad_utility::SameAsAny<char*, const char*> T>(T ptr) {
using Res = std::conditional_t<std::same_as<T, const char*>,
const unsigned char*, unsigned char*>;
return reinterpret_cast<Res>(ptr);
};
struct CastToUnsignedPtr {
CPP_template(typename T)(
requires ad_utility::SameAsAny<T, char*, const char*>) auto
operator()(T ptr) const {
using Res = std::conditional_t<std::same_as<T, const char*>,
const unsigned char*, unsigned char*>;
return reinterpret_cast<Res>(ptr);
};
};
constexpr CastToUnsignedPtr castToUnsignedPtr{};
} // namespace detail

// A simple C++ wrapper around the C-API of the `FSST` library. It consists of
Expand Down
6 changes: 2 additions & 4 deletions src/util/Iterators.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@
// Chair of Algorithms and Data Structures.
// Author: Johannes Kalmbach <[email protected]>

#ifndef QLEVER_ITERATORS_H
#define QLEVER_ITERATORS_H
#pragma once

#include <cstdint>
#include <iterator>
#include <type_traits>

#include "backports/algorithm.h"
#include "util/Enums.h"
#include "util/TypeTraits.h"

Expand Down Expand Up @@ -399,5 +399,3 @@ class InputRangeTypeErased {
using iterator = typename InputRangeFromGet<ValueType>::Iterator;
};
} // namespace ad_utility

#endif // QLEVER_ITERATORS_H
5 changes: 3 additions & 2 deletions src/util/JoinAlgorithms/JoinAlgorithms.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <ranges>

#include "backports/algorithm.h"
#include "backports/concepts.h"
#include "engine/idTable/IdTable.h"
#include "global/Id.h"
#include "util/Generator.h"
Expand Down Expand Up @@ -762,8 +763,8 @@ struct BlockZipperJoinImpl {
#if defined(Side) || defined(Blocks)
#error Side or Blocks are already defined
#endif
#define Side SameAsAny<LeftSide, RightSide> auto
#define Blocks SameAsAny<LeftBlocks, RightBlocks> auto
#define Side QL_CONCEPT_OR_NOTHING(SameAsAny<LeftSide, RightSide>) auto
#define Blocks QL_CONCEPT_OR_NOTHING(SameAsAny<LeftBlocks, RightBlocks>) auto

// Type alias for the result of the projection. Elements from the left and
// right input must be projected to the same type.
Expand Down
4 changes: 2 additions & 2 deletions src/util/TypeTraits.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#include <variant>
#include <vector>

#include "backports/algorithm.h"
#include "backports/concepts.h"
#include "util/Forward.h"

namespace ad_utility {
Expand Down Expand Up @@ -136,7 +136,7 @@ concept SimilarToAny = (... || isSimilar<T, Ts>);

/// True iff `T` is the same as any of the `Ts...`.
template <typename T, typename... Ts>
concept SameAsAny = (... || ql::concepts::same_as<T, Ts>);
CPP_concept SameAsAny = (... || ql::concepts::same_as<T, Ts>);

/*
The implementation for `SimilarToAnyTypeIn` and `SameAsAnyTypeIn` (see below
Expand Down
3 changes: 2 additions & 1 deletion src/util/Views.h
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,8 @@ CPP_template(typename Range, typename ElementType)(
generator<std::span<ElementType>> reChunkAtSeparator(
Range generator, ElementType separator) {
std::vector<ElementType> buffer;
for (QL_OPT_CONCEPT(ql::ranges::input_range) auto const& chunk : generator) {
for (QL_CONCEPT_OR_NOTHING(ql::ranges::input_range) auto const& chunk :
generator) {
for (ElementType c : chunk) {
if (c == separator) {
co_yield std::span{buffer.data(), buffer.size()};
Expand Down
6 changes: 3 additions & 3 deletions test/ConfigOptionProxyTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ namespace ad_utility {
@tparam OptionType Exists to define, if the test should be done with
`ConfigOption`, or `const ConfigOption`.
*/
template <template <typename> typename ProxyType,
SameAsAny<ConfigOption, const ConfigOption> OptionType>
void basicConstructorTest() {
CPP_template(template <typename> typename ProxyType, typename OptionType)(
requires SameAsAny<OptionType, ConfigOption,
const ConfigOption>) void basicConstructorTest() {
// Test construction for a given type.
auto doTest = []<typename T>() {
// Does the normal constructor work?
Expand Down

0 comments on commit 3b83918

Please sign in to comment.