return mpark variant

This commit is contained in:
2019-05-27 14:49:14 +07:00
parent 54bfb2d5ba
commit 608f9aae9b
27 changed files with 3838 additions and 274 deletions

3
.gitmodules vendored
View File

@@ -34,3 +34,6 @@
[submodule "modules/flat.hpp"]
path = modules/flat.hpp
url = https://github.com/BlackMATov/flat.hpp
[submodule "modules/variant"]
path = modules/variant
url = https://github.com/mpark/variant

View File

@@ -0,0 +1,23 @@
/*******************************************************************************
* This file is part of the "https://github.com/blackmatov/flat.hpp"
* For conditions of distribution and use, see copyright notice in LICENSE.md
* Copyright (C) 2019, by Matvey Cherevko (blackmatov@gmail.com)
******************************************************************************/
#pragma once
#include <type_traits>
namespace flat_hpp::detail
{
template < typename T, typename U, typename = void >
struct is_transparent
: std::false_type {};
template < typename T, typename U >
struct is_transparent<T, U, std::void_t<typename T::is_transparent>>
: std::true_type {};
template < typename T, typename U >
inline constexpr bool is_transparent_v = is_transparent<T, U>::value;
}

View File

@@ -0,0 +1,62 @@
/*******************************************************************************
* This file is part of the "https://github.com/blackmatov/flat.hpp"
* For conditions of distribution and use, see copyright notice in LICENSE.md
* Copyright (C) 2019, by Matvey Cherevko (blackmatov@gmail.com)
******************************************************************************/
#pragma once
#include "is_transparent.hpp"
namespace flat_hpp::detail
{
template < typename Pair, typename Compare >
class pair_compare : public Compare {
public:
pair_compare() = default;
pair_compare(const Compare& compare)
: Compare(compare) {}
bool operator()(
const typename Pair::first_type& l,
const typename Pair::first_type& r) const
{
return Compare::operator()(l, r);
}
bool operator()(const Pair& l, const Pair& r) const {
return Compare::operator()(l.first, r.first);
}
bool operator()(
const typename Pair::first_type& l,
const Pair& r) const
{
return Compare::operator()(l, r.first);
}
bool operator()(
const Pair& l,
const typename Pair::first_type& r) const
{
return Compare::operator()(l.first, r);
}
template < typename K >
std::enable_if_t<
is_transparent_v<Compare, K>,
bool>
operator()(const K& l, const Pair& r) const {
return Compare::operator()(l, r.first);
}
template < typename K >
std::enable_if_t<
is_transparent_v<Compare, K>,
bool>
operator()(const Pair& l, const K& r) const {
return Compare::operator()(l.first, r);
}
};
}

View File

@@ -15,55 +15,21 @@
#include <type_traits>
#include <initializer_list>
#include "detail/pair_compare.hpp"
#include "detail/is_transparent.hpp"
namespace flat_hpp
{
namespace detail
{
template < typename Value, typename Compare >
class flat_map_compare : public Compare {
public:
flat_map_compare() = default;
flat_map_compare(const Compare& compare)
: Compare(compare) {}
bool operator()(
const typename Value::first_type& l,
const typename Value::first_type& r) const
{
return Compare::operator()(l, r);
}
bool operator()(
const typename Value::first_type& l,
const Value& r) const
{
return Compare::operator()(l, r.first);
}
bool operator()(
const Value& l,
const typename Value::first_type& r) const
{
return Compare::operator()(l.first, r);
}
bool operator()(const Value& l, const Value& r) const {
return Compare::operator()(l.first, r.first);
}
};
}
template < typename Key
, typename Value
, typename Compare = std::less<Key>
, typename Container = std::vector<std::pair<Key, Value>> >
class flat_map
: private detail::flat_map_compare<
: private detail::pair_compare<
typename Container::value_type,
Compare>
{
using base_type = detail::flat_map_compare<
using base_type = detail::pair_compare<
typename Container::value_type,
Compare>;
public:
@@ -299,6 +265,30 @@ namespace flat_hpp
throw std::out_of_range("flat_map::at: key not found");
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
mapped_type&>
at(const K& key) {
const iterator iter = find(key);
if ( iter != end() ) {
return iter->second;
}
throw std::out_of_range("flat_map::at: key not found");
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
const mapped_type&>
at(const K& key) const {
const const_iterator iter = find(key);
if ( iter != end() ) {
return iter->second;
}
throw std::out_of_range("flat_map::at: key not found");
}
std::pair<iterator, bool> insert(value_type&& value) {
const iterator iter = lower_bound(value.first);
return iter == end() || this->operator()(value, *iter)
@@ -362,7 +352,7 @@ namespace flat_hpp
}
size_type erase(const key_type& key) {
const iterator iter = find(key);
const const_iterator iter = find(key);
return iter != end()
? (erase(iter), 1)
: 0;
@@ -384,16 +374,47 @@ namespace flat_hpp
return iter != end() ? 1 : 0;
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
size_type>
count(const K& key) const {
const const_iterator iter = find(key);
return iter != end() ? 1 : 0;
}
iterator find(const key_type& key) {
const iterator iter = lower_bound(key);
return iter != end() && !this->operator()(key, iter->first)
return iter != end() && !this->operator()(key, *iter)
? iter
: end();
}
const_iterator find(const key_type& key) const {
const const_iterator iter = lower_bound(key);
return iter != end() && !this->operator()(key, iter->first)
return iter != end() && !this->operator()(key, *iter)
? iter
: end();
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
iterator>
find(const K& key) {
const iterator iter = lower_bound(key);
return iter != end() && !this->operator()(key, *iter)
? iter
: end();
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
const_iterator>
find(const K& key) const {
const const_iterator iter = lower_bound(key);
return iter != end() && !this->operator()(key, *iter)
? iter
: end();
}
@@ -408,6 +429,24 @@ namespace flat_hpp
return std::equal_range(begin(), end(), key, comp);
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
std::pair<iterator, iterator>>
equal_range(const K& key) {
const base_type& comp = *this;
return std::equal_range(begin(), end(), key, comp);
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
std::pair<const_iterator, const_iterator>>
equal_range(const K& key) const {
const base_type& comp = *this;
return std::equal_range(begin(), end(), key, comp);
}
iterator lower_bound(const key_type& key) {
const base_type& comp = *this;
return std::lower_bound(begin(), end(), key, comp);
@@ -418,6 +457,24 @@ namespace flat_hpp
return std::lower_bound(begin(), end(), key, comp);
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
iterator>
lower_bound(const K& key) {
const base_type& comp = *this;
return std::lower_bound(begin(), end(), key, comp);
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
const_iterator>
lower_bound(const K& key) const {
const base_type& comp = *this;
return std::lower_bound(begin(), end(), key, comp);
}
iterator upper_bound(const key_type& key) {
const base_type& comp = *this;
return std::upper_bound(begin(), end(), key, comp);
@@ -428,6 +485,24 @@ namespace flat_hpp
return std::upper_bound(begin(), end(), key, comp);
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
iterator>
upper_bound(const K& key) {
const base_type& comp = *this;
return std::upper_bound(begin(), end(), key, comp);
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
const_iterator>
upper_bound(const K& key) const {
const base_type& comp = *this;
return std::upper_bound(begin(), end(), key, comp);
}
key_compare key_comp() const {
return *this;
}

View File

@@ -15,55 +15,21 @@
#include <type_traits>
#include <initializer_list>
#include "detail/pair_compare.hpp"
#include "detail/is_transparent.hpp"
namespace flat_hpp
{
namespace detail
{
template < typename Value, typename Compare >
class flat_multimap_compare : public Compare {
public:
flat_multimap_compare() = default;
flat_multimap_compare(const Compare& compare)
: Compare(compare) {}
bool operator()(
const typename Value::first_type& l,
const typename Value::first_type& r) const
{
return Compare::operator()(l, r);
}
bool operator()(
const typename Value::first_type& l,
const Value& r) const
{
return Compare::operator()(l, r.first);
}
bool operator()(
const Value& l,
const typename Value::first_type& r) const
{
return Compare::operator()(l.first, r);
}
bool operator()(const Value& l, const Value& r) const {
return Compare::operator()(l.first, r.first);
}
};
}
template < typename Key
, typename Value
, typename Compare = std::less<Key>
, typename Container = std::vector<std::pair<Key, Value>> >
class flat_multimap
: private detail::flat_multimap_compare<
: private detail::pair_compare<
typename Container::value_type,
Compare>
{
using base_type = detail::flat_multimap_compare<
using base_type = detail::pair_compare<
typename Container::value_type,
Compare>;
public:
@@ -299,6 +265,30 @@ namespace flat_hpp
throw std::out_of_range("flat_multimap::at: key not found");
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
mapped_type&>
at(const K& key) {
const iterator iter = find(key);
if ( iter != end() ) {
return iter->second;
}
throw std::out_of_range("flat_multimap::at: key not found");
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
const mapped_type&>
at(const K& key) const {
const const_iterator iter = find(key);
if ( iter != end() ) {
return iter->second;
}
throw std::out_of_range("flat_multimap::at: key not found");
}
iterator insert(value_type&& value) {
const iterator iter = upper_bound(value.first);
return data_.insert(iter, std::move(value));
@@ -380,16 +370,47 @@ namespace flat_hpp
return std::distance(p.first, p.second);
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
size_type>
count(const K& key) const {
const auto p = equal_range(key);
return std::distance(p.first, p.second);
}
iterator find(const key_type& key) {
const iterator iter = lower_bound(key);
return iter != end() && !this->operator()(key, iter->first)
return iter != end() && !this->operator()(key, *iter)
? iter
: end();
}
const_iterator find(const key_type& key) const {
const const_iterator iter = lower_bound(key);
return iter != end() && !this->operator()(key, iter->first)
return iter != end() && !this->operator()(key, *iter)
? iter
: end();
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
iterator>
find(const K& key) {
const iterator iter = lower_bound(key);
return iter != end() && !this->operator()(key, *iter)
? iter
: end();
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
const_iterator>
find(const K& key) const {
const const_iterator iter = lower_bound(key);
return iter != end() && !this->operator()(key, *iter)
? iter
: end();
}
@@ -404,6 +425,24 @@ namespace flat_hpp
return std::equal_range(begin(), end(), key, comp);
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
std::pair<iterator, iterator>>
equal_range(const K& key) {
const base_type& comp = *this;
return std::equal_range(begin(), end(), key, comp);
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
std::pair<const_iterator, const_iterator>>
equal_range(const K& key) const {
const base_type& comp = *this;
return std::equal_range(begin(), end(), key, comp);
}
iterator lower_bound(const key_type& key) {
const base_type& comp = *this;
return std::lower_bound(begin(), end(), key, comp);
@@ -414,6 +453,24 @@ namespace flat_hpp
return std::lower_bound(begin(), end(), key, comp);
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
iterator>
lower_bound(const K& key) {
const base_type& comp = *this;
return std::lower_bound(begin(), end(), key, comp);
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
const_iterator>
lower_bound(const K& key) const {
const base_type& comp = *this;
return std::lower_bound(begin(), end(), key, comp);
}
iterator upper_bound(const key_type& key) {
const base_type& comp = *this;
return std::upper_bound(begin(), end(), key, comp);
@@ -424,6 +481,24 @@ namespace flat_hpp
return std::upper_bound(begin(), end(), key, comp);
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
iterator>
upper_bound(const K& key) {
const base_type& comp = *this;
return std::upper_bound(begin(), end(), key, comp);
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
const_iterator>
upper_bound(const K& key) const {
const base_type& comp = *this;
return std::upper_bound(begin(), end(), key, comp);
}
key_compare key_comp() const {
return *this;
}

View File

@@ -15,6 +15,8 @@
#include <type_traits>
#include <initializer_list>
#include "detail/is_transparent.hpp"
namespace flat_hpp
{
template < typename Key
@@ -295,6 +297,15 @@ namespace flat_hpp
return std::distance(p.first, p.second);
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
size_type>
count(const K& key) const {
const auto p = equal_range(key);
return std::distance(p.first, p.second);
}
iterator find(const key_type& key) {
const iterator iter = lower_bound(key);
return iter != end() && !this->operator()(key, *iter)
@@ -309,6 +320,28 @@ namespace flat_hpp
: end();
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
iterator>
find(const K& key) {
const iterator iter = lower_bound(key);
return iter != end() && !this->operator()(key, *iter)
? iter
: end();
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
const_iterator>
find(const K& key) const {
const const_iterator iter = lower_bound(key);
return iter != end() && !this->operator()(key, *iter)
? iter
: end();
}
std::pair<iterator, iterator> equal_range(const key_type& key) {
return std::equal_range(begin(), end(), key, key_comp());
}
@@ -317,6 +350,22 @@ namespace flat_hpp
return std::equal_range(begin(), end(), key, key_comp());
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
std::pair<iterator, iterator>>
equal_range(const K& key) {
return std::equal_range(begin(), end(), key, key_comp());
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
std::pair<const_iterator, const_iterator>>
equal_range(const K& key) const {
return std::equal_range(begin(), end(), key, key_comp());
}
iterator lower_bound(const key_type& key) {
return std::lower_bound(begin(), end(), key, key_comp());
}
@@ -325,6 +374,22 @@ namespace flat_hpp
return std::lower_bound(begin(), end(), key, key_comp());
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
iterator>
lower_bound(const K& key) {
return std::lower_bound(begin(), end(), key, key_comp());
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
const_iterator>
lower_bound(const K& key) const {
return std::lower_bound(begin(), end(), key, key_comp());
}
iterator upper_bound(const key_type& key) {
return std::upper_bound(begin(), end(), key, key_comp());
}
@@ -333,6 +398,22 @@ namespace flat_hpp
return std::upper_bound(begin(), end(), key, key_comp());
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
iterator>
upper_bound(const K& key) {
return std::upper_bound(begin(), end(), key, key_comp());
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
const_iterator>
upper_bound(const K& key) const {
return std::upper_bound(begin(), end(), key, key_comp());
}
key_compare key_comp() const {
return *this;
}

View File

@@ -15,6 +15,8 @@
#include <type_traits>
#include <initializer_list>
#include "detail/is_transparent.hpp"
namespace flat_hpp
{
template < typename Key
@@ -277,7 +279,7 @@ namespace flat_hpp
}
size_type erase(const key_type& key) {
const iterator iter = find(key);
const const_iterator iter = find(key);
return iter != end()
? (erase(iter), 1)
: 0;
@@ -299,6 +301,15 @@ namespace flat_hpp
return iter != end() ? 1 : 0;
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
size_type>
count(const K& key) const {
const const_iterator iter = find(key);
return iter != end() ? 1 : 0;
}
iterator find(const key_type& key) {
const iterator iter = lower_bound(key);
return iter != end() && !this->operator()(key, *iter)
@@ -313,6 +324,28 @@ namespace flat_hpp
: end();
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
iterator>
find(const K& key) {
const iterator iter = lower_bound(key);
return iter != end() && !this->operator()(key, *iter)
? iter
: end();
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
const_iterator>
find(const K& key) const {
const const_iterator iter = lower_bound(key);
return iter != end() && !this->operator()(key, *iter)
? iter
: end();
}
std::pair<iterator, iterator> equal_range(const key_type& key) {
return std::equal_range(begin(), end(), key, key_comp());
}
@@ -321,6 +354,22 @@ namespace flat_hpp
return std::equal_range(begin(), end(), key, key_comp());
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
std::pair<iterator, iterator>>
equal_range(const K& key) {
return std::equal_range(begin(), end(), key, key_comp());
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
std::pair<const_iterator, const_iterator>>
equal_range(const K& key) const {
return std::equal_range(begin(), end(), key, key_comp());
}
iterator lower_bound(const key_type& key) {
return std::lower_bound(begin(), end(), key, key_comp());
}
@@ -329,6 +378,22 @@ namespace flat_hpp
return std::lower_bound(begin(), end(), key, key_comp());
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
iterator>
lower_bound(const K& key) {
return std::lower_bound(begin(), end(), key, key_comp());
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
const_iterator>
lower_bound(const K& key) const {
return std::lower_bound(begin(), end(), key, key_comp());
}
iterator upper_bound(const key_type& key) {
return std::upper_bound(begin(), end(), key, key_comp());
}
@@ -337,6 +402,22 @@ namespace flat_hpp
return std::upper_bound(begin(), end(), key, key_comp());
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
iterator>
upper_bound(const K& key) {
return std::upper_bound(begin(), end(), key, key_comp());
}
template < typename K >
std::enable_if_t<
detail::is_transparent_v<Compare, K>,
const_iterator>
upper_bound(const K& key) const {
return std::upper_bound(begin(), end(), key, key_comp());
}
key_compare key_comp() const {
return *this;
}

96
headers/3rdparty/variant/config.hpp vendored Normal file
View File

@@ -0,0 +1,96 @@
// MPark.Variant
//
// Copyright Michael Park, 2015-2017
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
#ifndef MPARK_CONFIG_HPP
#define MPARK_CONFIG_HPP
// MSVC 2015 Update 3.
#if __cplusplus < 201103L && (!defined(_MSC_VER) || _MSC_FULL_VER < 190024210)
#error "MPark.Variant requires C++11 support."
#endif
#ifndef __has_attribute
#define __has_attribute(x) 0
#endif
#ifndef __has_builtin
#define __has_builtin(x) 0
#endif
#ifndef __has_include
#define __has_include(x) 0
#endif
#ifndef __has_feature
#define __has_feature(x) 0
#endif
#if __has_attribute(always_inline) || defined(__GNUC__)
#define MPARK_ALWAYS_INLINE __attribute__((__always_inline__)) inline
#elif defined(_MSC_VER)
#define MPARK_ALWAYS_INLINE __forceinline
#else
#define MPARK_ALWAYS_INLINE inline
#endif
#if __has_builtin(__builtin_addressof) || \
(defined(__GNUC__) && __GNUC__ >= 7) || defined(_MSC_VER)
#define MPARK_BUILTIN_ADDRESSOF
#endif
#if __has_builtin(__builtin_unreachable) || defined(__GNUC__)
#define MPARK_BUILTIN_UNREACHABLE __builtin_unreachable()
#elif defined(_MSC_VER)
#define MPARK_BUILTIN_UNREACHABLE __assume(false)
#else
#define MPARK_BUILTIN_UNREACHABLE
#endif
#if __has_builtin(__type_pack_element)
#define MPARK_TYPE_PACK_ELEMENT
#endif
#if defined(__cpp_constexpr) && __cpp_constexpr >= 200704 && \
!(defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 9)
#define MPARK_CPP11_CONSTEXPR
#endif
#if defined(__cpp_constexpr) && __cpp_constexpr >= 201304
#define MPARK_CPP14_CONSTEXPR
#endif
#if __has_feature(cxx_exceptions) || defined(__cpp_exceptions) || \
(defined(_MSC_VER) && defined(_CPPUNWIND))
#define MPARK_EXCEPTIONS
#endif
#if defined(__cpp_generic_lambdas) || defined(_MSC_VER)
#define MPARK_GENERIC_LAMBDAS
#endif
#if defined(__cpp_lib_integer_sequence)
#define MPARK_INTEGER_SEQUENCE
#endif
#if defined(__cpp_return_type_deduction) || defined(_MSC_VER)
#define MPARK_RETURN_TYPE_DEDUCTION
#endif
#if defined(__cpp_lib_transparent_operators) || defined(_MSC_VER)
#define MPARK_TRANSPARENT_OPERATORS
#endif
#if defined(__cpp_variable_templates) || defined(_MSC_VER)
#define MPARK_VARIABLE_TEMPLATES
#endif
#if !defined(__GLIBCXX__) || __has_include(<codecvt>) // >= libstdc++-5
#define MPARK_TRIVIALITY_TYPE_TRAITS
#define MPARK_INCOMPLETE_TYPE_TRAITS
#endif
#endif // MPARK_CONFIG_HPP

35
headers/3rdparty/variant/in_place.hpp vendored Normal file
View File

@@ -0,0 +1,35 @@
// MPark.Variant
//
// Copyright Michael Park, 2015-2017
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
#ifndef MPARK_IN_PLACE_HPP
#define MPARK_IN_PLACE_HPP
#include <cstddef>
#include "config.hpp"
namespace mpark {
struct in_place_t { explicit in_place_t() = default; };
template <std::size_t I>
struct in_place_index_t { explicit in_place_index_t() = default; };
template <typename T>
struct in_place_type_t { explicit in_place_type_t() = default; };
#ifdef MPARK_VARIABLE_TEMPLATES
constexpr in_place_t in_place{};
template <std::size_t I> constexpr in_place_index_t<I> in_place_index{};
template <typename T> constexpr in_place_type_t<T> in_place_type{};
#endif
} // namespace mpark
#endif // MPARK_IN_PLACE_HPP

499
headers/3rdparty/variant/lib.hpp vendored Normal file
View File

@@ -0,0 +1,499 @@
// MPark.Variant
//
// Copyright Michael Park, 2015-2017
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
#ifndef MPARK_LIB_HPP
#define MPARK_LIB_HPP
#include <memory>
#include <functional>
#include <type_traits>
#include <utility>
#include "config.hpp"
#define MPARK_RETURN(...) \
noexcept(noexcept(__VA_ARGS__)) -> decltype(__VA_ARGS__) { return __VA_ARGS__; }
namespace mpark {
namespace lib {
template <typename T>
struct identity { using type = T; };
inline namespace cpp14 {
template <typename T, std::size_t N>
struct array {
constexpr const T &operator[](std::size_t index) const {
return data[index];
}
T data[N == 0 ? 1 : N];
};
template <typename T>
using add_pointer_t = typename std::add_pointer<T>::type;
template <typename... Ts>
using common_type_t = typename std::common_type<Ts...>::type;
template <typename T>
using decay_t = typename std::decay<T>::type;
template <bool B, typename T = void>
using enable_if_t = typename std::enable_if<B, T>::type;
template <typename T>
using remove_const_t = typename std::remove_const<T>::type;
template <typename T>
using remove_reference_t = typename std::remove_reference<T>::type;
template <typename T>
inline constexpr T &&forward(remove_reference_t<T> &t) noexcept {
return static_cast<T &&>(t);
}
template <typename T>
inline constexpr T &&forward(remove_reference_t<T> &&t) noexcept {
static_assert(!std::is_lvalue_reference<T>::value,
"can not forward an rvalue as an lvalue");
return static_cast<T &&>(t);
}
template <typename T>
inline constexpr remove_reference_t<T> &&move(T &&t) noexcept {
return static_cast<remove_reference_t<T> &&>(t);
}
#ifdef MPARK_INTEGER_SEQUENCE
using std::integer_sequence;
using std::index_sequence;
using std::make_index_sequence;
using std::index_sequence_for;
#else
template <typename T, T... Is>
struct integer_sequence {
using value_type = T;
static constexpr std::size_t size() noexcept { return sizeof...(Is); }
};
template <std::size_t... Is>
using index_sequence = integer_sequence<std::size_t, Is...>;
template <typename Lhs, typename Rhs>
struct make_index_sequence_concat;
template <std::size_t... Lhs, std::size_t... Rhs>
struct make_index_sequence_concat<index_sequence<Lhs...>,
index_sequence<Rhs...>>
: identity<index_sequence<Lhs..., (sizeof...(Lhs) + Rhs)...>> {};
template <std::size_t N>
struct make_index_sequence_impl;
template <std::size_t N>
using make_index_sequence = typename make_index_sequence_impl<N>::type;
template <std::size_t N>
struct make_index_sequence_impl
: make_index_sequence_concat<make_index_sequence<N / 2>,
make_index_sequence<N - (N / 2)>> {};
template <>
struct make_index_sequence_impl<0> : identity<index_sequence<>> {};
template <>
struct make_index_sequence_impl<1> : identity<index_sequence<0>> {};
template <typename... Ts>
using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
#endif
// <functional>
#ifdef MPARK_TRANSPARENT_OPERATORS
using equal_to = std::equal_to<>;
#else
struct equal_to {
template <typename Lhs, typename Rhs>
inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
MPARK_RETURN(lib::forward<Lhs>(lhs) == lib::forward<Rhs>(rhs))
};
#endif
#ifdef MPARK_TRANSPARENT_OPERATORS
using not_equal_to = std::not_equal_to<>;
#else
struct not_equal_to {
template <typename Lhs, typename Rhs>
inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
MPARK_RETURN(lib::forward<Lhs>(lhs) != lib::forward<Rhs>(rhs))
};
#endif
#ifdef MPARK_TRANSPARENT_OPERATORS
using less = std::less<>;
#else
struct less {
template <typename Lhs, typename Rhs>
inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
MPARK_RETURN(lib::forward<Lhs>(lhs) < lib::forward<Rhs>(rhs))
};
#endif
#ifdef MPARK_TRANSPARENT_OPERATORS
using greater = std::greater<>;
#else
struct greater {
template <typename Lhs, typename Rhs>
inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
MPARK_RETURN(lib::forward<Lhs>(lhs) > lib::forward<Rhs>(rhs))
};
#endif
#ifdef MPARK_TRANSPARENT_OPERATORS
using less_equal = std::less_equal<>;
#else
struct less_equal {
template <typename Lhs, typename Rhs>
inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
MPARK_RETURN(lib::forward<Lhs>(lhs) <= lib::forward<Rhs>(rhs))
};
#endif
#ifdef MPARK_TRANSPARENT_OPERATORS
using greater_equal = std::greater_equal<>;
#else
struct greater_equal {
template <typename Lhs, typename Rhs>
inline constexpr auto operator()(Lhs &&lhs, Rhs &&rhs) const
MPARK_RETURN(lib::forward<Lhs>(lhs) >= lib::forward<Rhs>(rhs))
};
#endif
} // namespace cpp14
inline namespace cpp17 {
// <type_traits>
template <bool B>
using bool_constant = std::integral_constant<bool, B>;
template <typename...>
struct voider : identity<void> {};
template <typename... Ts>
using void_t = typename voider<Ts...>::type;
namespace detail {
namespace swappable {
using std::swap;
template <typename T>
struct is_swappable {
private:
template <typename U,
typename = decltype(swap(std::declval<U &>(),
std::declval<U &>()))>
inline static std::true_type test(int);
template <typename U>
inline static std::false_type test(...);
public:
static constexpr bool value = decltype(test<T>(0))::value;
};
template <bool IsSwappable, typename T>
struct is_nothrow_swappable {
static constexpr bool value =
noexcept(swap(std::declval<T &>(), std::declval<T &>()));
};
template <typename T>
struct is_nothrow_swappable<false, T> : std::false_type {};
} // namespace swappable
} // namespace detail
using detail::swappable::is_swappable;
template <typename T>
using is_nothrow_swappable =
detail::swappable::is_nothrow_swappable<is_swappable<T>::value, T>;
// <functional>
namespace detail {
template <typename T>
struct is_reference_wrapper : std::false_type {};
template <typename T>
struct is_reference_wrapper<std::reference_wrapper<T>>
: std::true_type {};
template <bool, int>
struct Invoke;
template <>
struct Invoke<true /* pmf */, 0 /* is_base_of */> {
template <typename R, typename T, typename Arg, typename... Args>
inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args)
MPARK_RETURN((lib::forward<Arg>(arg).*pmf)(lib::forward<Args>(args)...))
};
template <>
struct Invoke<true /* pmf */, 1 /* is_reference_wrapper */> {
template <typename R, typename T, typename Arg, typename... Args>
inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args)
MPARK_RETURN((lib::forward<Arg>(arg).get().*pmf)(lib::forward<Args>(args)...))
};
template <>
struct Invoke<true /* pmf */, 2 /* otherwise */> {
template <typename R, typename T, typename Arg, typename... Args>
inline static constexpr auto invoke(R T::*pmf, Arg &&arg, Args &&... args)
MPARK_RETURN(((*lib::forward<Arg>(arg)).*pmf)(lib::forward<Args>(args)...))
};
template <>
struct Invoke<false /* pmo */, 0 /* is_base_of */> {
template <typename R, typename T, typename Arg>
inline static constexpr auto invoke(R T::*pmo, Arg &&arg)
MPARK_RETURN(lib::forward<Arg>(arg).*pmo)
};
template <>
struct Invoke<false /* pmo */, 1 /* is_reference_wrapper */> {
template <typename R, typename T, typename Arg>
inline static constexpr auto invoke(R T::*pmo, Arg &&arg)
MPARK_RETURN(lib::forward<Arg>(arg).get().*pmo)
};
template <>
struct Invoke<false /* pmo */, 2 /* otherwise */> {
template <typename R, typename T, typename Arg>
inline static constexpr auto invoke(R T::*pmo, Arg &&arg)
MPARK_RETURN((*lib::forward<Arg>(arg)).*pmo)
};
template <typename R, typename T, typename Arg, typename... Args>
inline constexpr auto invoke(R T::*f, Arg &&arg, Args &&... args)
MPARK_RETURN(
Invoke<std::is_function<R>::value,
(std::is_base_of<T, lib::decay_t<Arg>>::value
? 0
: is_reference_wrapper<lib::decay_t<Arg>>::value
? 1
: 2)>::invoke(f,
lib::forward<Arg>(arg),
lib::forward<Args>(args)...))
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4100)
#endif
template <typename F, typename... Args>
inline constexpr auto invoke(F &&f, Args &&... args)
MPARK_RETURN(lib::forward<F>(f)(lib::forward<Args>(args)...))
#ifdef _MSC_VER
#pragma warning(pop)
#endif
} // namespace detail
template <typename F, typename... Args>
inline constexpr auto invoke(F &&f, Args &&... args)
MPARK_RETURN(detail::invoke(lib::forward<F>(f),
lib::forward<Args>(args)...))
namespace detail {
template <typename Void, typename, typename...>
struct invoke_result {};
template <typename F, typename... Args>
struct invoke_result<void_t<decltype(lib::invoke(
std::declval<F>(), std::declval<Args>()...))>,
F,
Args...>
: identity<decltype(
lib::invoke(std::declval<F>(), std::declval<Args>()...))> {};
} // namespace detail
template <typename F, typename... Args>
using invoke_result = detail::invoke_result<void, F, Args...>;
template <typename F, typename... Args>
using invoke_result_t = typename invoke_result<F, Args...>::type;
namespace detail {
template <typename Void, typename, typename...>
struct is_invocable : std::false_type {};
template <typename F, typename... Args>
struct is_invocable<void_t<invoke_result_t<F, Args...>>, F, Args...>
: std::true_type {};
template <typename Void, typename, typename, typename...>
struct is_invocable_r : std::false_type {};
template <typename R, typename F, typename... Args>
struct is_invocable_r<void_t<invoke_result_t<F, Args...>>,
R,
F,
Args...>
: std::is_convertible<invoke_result_t<F, Args...>, R> {};
} // namespace detail
template <typename F, typename... Args>
using is_invocable = detail::is_invocable<void, F, Args...>;
template <typename R, typename F, typename... Args>
using is_invocable_r = detail::is_invocable_r<void, R, F, Args...>;
// <memory>
#ifdef MPARK_BUILTIN_ADDRESSOF
template <typename T>
inline constexpr T *addressof(T &arg) noexcept {
return __builtin_addressof(arg);
}
#else
namespace detail {
namespace has_addressof_impl {
struct fail;
template <typename T>
inline fail operator&(T &&);
template <typename T>
inline static constexpr bool impl() {
return (std::is_class<T>::value || std::is_union<T>::value) &&
!std::is_same<decltype(&std::declval<T &>()), fail>::value;
}
} // namespace has_addressof_impl
template <typename T>
using has_addressof = bool_constant<has_addressof_impl::impl<T>()>;
template <typename T>
inline constexpr T *addressof(T &arg, std::true_type) noexcept {
return std::addressof(arg);
}
template <typename T>
inline constexpr T *addressof(T &arg, std::false_type) noexcept {
return &arg;
}
} // namespace detail
template <typename T>
inline constexpr T *addressof(T &arg) noexcept {
return detail::addressof(arg, detail::has_addressof<T>{});
}
#endif
template <typename T>
inline constexpr T *addressof(const T &&) = delete;
} // namespace cpp17
template <typename T>
struct remove_all_extents : identity<T> {};
template <typename T, std::size_t N>
struct remove_all_extents<array<T, N>> : remove_all_extents<T> {};
template <typename T>
using remove_all_extents_t = typename remove_all_extents<T>::type;
template <std::size_t N>
using size_constant = std::integral_constant<std::size_t, N>;
template <std::size_t I, typename T>
struct indexed_type : size_constant<I> { using type = T; };
template <bool... Bs>
using all = std::is_same<integer_sequence<bool, true, Bs...>,
integer_sequence<bool, Bs..., true>>;
#ifdef MPARK_TYPE_PACK_ELEMENT
template <std::size_t I, typename... Ts>
using type_pack_element_t = __type_pack_element<I, Ts...>;
#else
template <std::size_t I, typename... Ts>
struct type_pack_element_impl {
private:
template <typename>
struct set;
template <std::size_t... Is>
struct set<index_sequence<Is...>> : indexed_type<Is, Ts>... {};
template <typename T>
inline static std::enable_if<true, T> impl(indexed_type<I, T>);
inline static std::enable_if<false> impl(...);
public:
using type = decltype(impl(set<index_sequence_for<Ts...>>{}));
};
template <std::size_t I, typename... Ts>
using type_pack_element = typename type_pack_element_impl<I, Ts...>::type;
template <std::size_t I, typename... Ts>
using type_pack_element_t = typename type_pack_element<I, Ts...>::type;
#endif
#ifdef MPARK_TRIVIALITY_TYPE_TRAITS
using std::is_trivially_copy_constructible;
using std::is_trivially_move_constructible;
using std::is_trivially_copy_assignable;
using std::is_trivially_move_assignable;
#else
template <typename T>
struct is_trivially_copy_constructible
: bool_constant<
std::is_copy_constructible<T>::value && __has_trivial_copy(T)> {};
template <typename T>
struct is_trivially_move_constructible : bool_constant<__is_trivial(T)> {};
template <typename T>
struct is_trivially_copy_assignable
: bool_constant<
std::is_copy_assignable<T>::value && __has_trivial_assign(T)> {};
template <typename T>
struct is_trivially_move_assignable : bool_constant<__is_trivial(T)> {};
#endif
template <typename T, bool>
struct dependent_type : T {};
template <typename Is, std::size_t J>
struct push_back;
template <typename Is, std::size_t J>
using push_back_t = typename push_back<Is, J>::type;
template <std::size_t... Is, std::size_t J>
struct push_back<index_sequence<Is...>, J> {
using type = index_sequence<Is..., J>;
};
} // namespace lib
} // namespace mpark
#undef MPARK_RETURN
#endif // MPARK_LIB_HPP

2156
headers/3rdparty/variant/variant.hpp vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -26,7 +26,6 @@
#include <bitset>
#include <string>
#include <vector>
#include <variant>
#include <unordered_set>
#include <unordered_map>

View File

@@ -8,6 +8,7 @@
#include "_base.hpp"
#include <3rdparty/variant/variant.hpp>
#include <3rdparty/flat.hpp/flat_set.hpp>
#include <3rdparty/flat.hpp/flat_map.hpp>
@@ -37,21 +38,21 @@ namespace e2d
using vector = std::vector<Value, Allocator>;
template < typename Key
, typename Comp = std::less<>
, typename Compare = std::less<>
, typename Allocator = std::allocator<Key> >
using set = std::set<Key, Comp, Allocator>;
using set = std::set<Key, Compare, Allocator>;
template < typename Key
, typename Value
, typename Comp = std::less<>
, typename Compare = std::less<>
, typename Allocator = std::allocator<std::pair<const Key, Value>> >
using map = std::map<Key, Value, Comp, Allocator>;
using map = std::map<Key, Value, Compare, Allocator>;
template < typename Value
, typename Hash = std::hash<Value>
template < typename Key
, typename Hash = std::hash<Key>
, typename Pred = std::equal_to<>
, typename Allocator = std::allocator<Value> >
using hash_set = std::unordered_set<Value, Hash, Pred, Allocator>;
, typename Allocator = std::allocator<Key> >
using hash_set = std::unordered_set<Key, Hash, Pred, Allocator>;
template < typename Key
, typename Value
@@ -83,3 +84,8 @@ namespace e2d
, typename Container = vector<std::pair<Key, Value>> >
using flat_map = flat_hpp::flat_map<Key, Value, Compare, Container>;
}
namespace e2d::stdex
{
using namespace mpark;
}

View File

@@ -609,7 +609,7 @@ namespace e2d
sampler_mag_filter mag_filter_ = sampler_mag_filter::linear;
};
using property_value = std::variant<
using property_value = stdex::variant<
i32, f32,
v2i, v3i, v4i,
v2f, v3f, v4f,
@@ -862,7 +862,7 @@ namespace e2d
bool scissoring_ = false;
};
using command_value = std::variant<
using command_value = stdex::variant<
zero_command,
draw_command,
clear_command,

View File

@@ -195,7 +195,7 @@ namespace e2d
const T* render::property_block::property(str_hash name) const noexcept {
const property_value* prop = properties_.find(name);
return prop
? std::get_if<T>(prop)
? stdex::get_if<T>(prop)
: nullptr;
}

1
modules/variant Submodule

Submodule modules/variant added at 99ef8fb19f

View File

@@ -67,3 +67,6 @@ cp -fv $MODULES_DIR/stb/stb_truetype.h $SOURCES_RDPARTY_DIR/stb/stb_truetype.h
mkdir -p $SOURCES_RDPARTY_DIR/utfcpp
cp -rfv $MODULES_DIR/utfcpp/source/. $SOURCES_RDPARTY_DIR/utfcpp/
mkdir -p $HEADERS_RDPARTY_DIR/variant
cp -rfv $MODULES_DIR/variant/include/mpark/. $HEADERS_RDPARTY_DIR/variant/

View File

@@ -1235,8 +1235,8 @@ static void ShowDemoWindowWidgets()
ImGui::Text("HSV encoded colors");
ImGui::SameLine(); HelpMarker("By default, colors are given to ColorEdit and ColorPicker in RGB, but ImGuiColorEditFlags_InputHSV allows you to store colors as HSV and pass them to ColorEdit and ColorPicker as HSV. This comes with the added benefit that you can manipulate hue values with the picker even when saturation or value are zero.");
ImGui::Text("Color widget with InputHSV:");
ImGui::ColorEdit4("HSV shown as HSV##1", (float*)&color_stored_as_hsv, ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_InputHSV | ImGuiColorEditFlags_Float);
ImGui::ColorEdit4("HSV shown as RGB##1", (float*)&color_stored_as_hsv, ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_InputHSV | ImGuiColorEditFlags_Float);
ImGui::ColorEdit4("HSV shown as RGB##1", (float*)&color_stored_as_hsv, ImGuiColorEditFlags_DisplayRGB | ImGuiColorEditFlags_InputHSV | ImGuiColorEditFlags_Float);
ImGui::ColorEdit4("HSV shown as HSV##1", (float*)&color_stored_as_hsv, ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_InputHSV | ImGuiColorEditFlags_Float);
ImGui::DragFloat4("Raw HSV values", (float*)&color_stored_as_hsv, 0.01f, 0.0f, 1.0f);
ImGui::TreePop();

View File

@@ -4258,7 +4258,7 @@ bool ImGui::ColorEdit4(const char* label, float col[4], ImGuiColorEditFlags flag
Spacing();
}
ImGuiColorEditFlags picker_flags_to_forward = ImGuiColorEditFlags__DataTypeMask | ImGuiColorEditFlags__PickerMask | ImGuiColorEditFlags__InputMask | ImGuiColorEditFlags_HDR | ImGuiColorEditFlags_NoAlpha | ImGuiColorEditFlags_AlphaBar;
ImGuiColorEditFlags picker_flags = (flags_untouched & picker_flags_to_forward) | ImGuiColorEditFlags_DisplayHSV | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_AlphaPreviewHalf;
ImGuiColorEditFlags picker_flags = (flags_untouched & picker_flags_to_forward) | ImGuiColorEditFlags__DisplayMask | ImGuiColorEditFlags_NoLabel | ImGuiColorEditFlags_AlphaPreviewHalf;
SetNextItemWidth(square_sz * 12.0f); // Use 256 + bar sizes?
value_changed |= ColorPicker4("##picker", col, picker_flags, &g.ColorPickerRef.x);
EndPopup();

View File

@@ -1141,7 +1141,7 @@ namespace e2d
render& render::execute(const command_value& command) {
E2D_ASSERT(is_in_main_thread());
E2D_ASSERT(!command.valueless_by_exception());
std::visit(command_value_visitor(*this), command);
stdex::visit(command_value_visitor(*this), command);
return *this;
}
}

View File

@@ -114,7 +114,7 @@ namespace
pb.foreach_by_properties([&debug, &ps](str_hash name, const render::property_value& value) noexcept {
ps->state().with_uniform_location(name, [&debug, &value](const uniform_info& ui) noexcept {
E2D_ASSERT(!value.valueless_by_exception());
std::visit(property_block_value_visitor(debug, ui), value);
stdex::visit(property_block_value_visitor(debug, ui), value);
});
});
GLint unit = 0;

File diff suppressed because it is too large Load Diff

View File

@@ -40,16 +40,16 @@ TEST_CASE("render"){
REQUIRE_FALSE(pb1.property<i32>("f"));
REQUIRE(pb1.property("i"));
REQUIRE(pb1.property("f"));
REQUIRE(std::get<i32>(*pb1.property("i")) == 42);
REQUIRE(std::get<f32>(*pb1.property("f")) == 1.f);
REQUIRE(stdex::get<i32>(*pb1.property("i")) == 42);
REQUIRE(stdex::get<f32>(*pb1.property("f")) == 1.f);
{
f32 acc = 0.f;
pb1.foreach_by_properties([&acc](str_hash n, const render::property_value& v){
if ( n == make_hash("f") ) {
acc += std::get<f32>(v);
acc += stdex::get<f32>(v);
}
if ( n == make_hash("i") ) {
acc += std::get<i32>(v);
acc += stdex::get<i32>(v);
}
});
REQUIRE(math::approximately(acc, 43.f));

View File

@@ -258,7 +258,7 @@ TEST_CASE("library"){
const auto* property = material_res->content().properties().property("i");
REQUIRE(property);
REQUIRE(property->index() == 0);
REQUIRE(std::get<i32>(*property) == 42);
REQUIRE(stdex::get<i32>(*property) == 42);
}
REQUIRE(material_res->content().pass_count() == 1);
const auto& pass = material_res->content().pass(0);
@@ -266,31 +266,31 @@ TEST_CASE("library"){
const auto* property = pass.properties().property("f");
REQUIRE(property);
REQUIRE(property->index() == 1);
REQUIRE(math::approximately(std::get<f32>(*property), 4.2f));
REQUIRE(math::approximately(stdex::get<f32>(*property), 4.2f));
}
{
const auto* property = pass.properties().property("v1");
REQUIRE(property);
REQUIRE(property->index() == 2);
REQUIRE(std::get<v2i>(*property) == v2i(1,2));
REQUIRE(stdex::get<v2i>(*property) == v2i(1,2));
}
{
const auto* property = pass.properties().property("v2");
REQUIRE(property);
REQUIRE(property->index() == 6);
REQUIRE(std::get<v3f>(*property) == v3f(3.f));
REQUIRE(stdex::get<v3f>(*property) == v3f(3.f));
}
{
const auto* property = pass.properties().property("v3");
REQUIRE(property);
REQUIRE(property->index() == 4);
REQUIRE(std::get<v4i>(*property) == v4i(1,2,3,4));
REQUIRE(stdex::get<v4i>(*property) == v4i(1,2,3,4));
}
{
const auto* property = pass.properties().property("m1");
REQUIRE(property);
REQUIRE(property->index() == 8);
REQUIRE(std::get<m2f>(*property) == m2f(1,2,3,4));
REQUIRE(stdex::get<m2f>(*property) == m2f(1,2,3,4));
const auto* property2 = pass.properties().property("m4");
REQUIRE(property2);
@@ -300,7 +300,7 @@ TEST_CASE("library"){
const auto* property = pass.properties().property("m2");
REQUIRE(property);
REQUIRE(property->index() == 9);
REQUIRE(std::get<m3f>(*property) == m3f(1,2,3,4,5,6,7,8,9));
REQUIRE(stdex::get<m3f>(*property) == m3f(1,2,3,4,5,6,7,8,9));
const auto* property2 = pass.properties().property("m5");
REQUIRE(property2);
@@ -310,7 +310,7 @@ TEST_CASE("library"){
const auto* property = pass.properties().property("m3");
REQUIRE(property);
REQUIRE(property->index() == 10);
REQUIRE(std::get<m4f>(*property) == m4f(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16));
REQUIRE(stdex::get<m4f>(*property) == m4f(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16));
const auto* property2 = pass.properties().property("m6");
REQUIRE(property2);