118 lines
3.9 KiB
C++
118 lines
3.9 KiB
C++
/**
|
|
This file is a part of rexy's general purpose library
|
|
Copyright (C) 2022 rexy712
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef REXY_DETAIL_FORMAT_NAMED_ARGS_HPP
|
|
#define REXY_DETAIL_FORMAT_NAMED_ARGS_HPP
|
|
|
|
#include <type_traits> //remove_cvref, declval, integral_constant
|
|
#include <utility> //forward
|
|
#include <cstddef> //size_t
|
|
|
|
#include "../../string_view.hpp"
|
|
|
|
namespace rexy::fmt{
|
|
|
|
namespace detail{
|
|
|
|
template<class T, class Char>
|
|
struct arg_base{
|
|
const T& value;
|
|
const basic_string_view<Char> name;
|
|
};
|
|
|
|
//class used to store name and value for runtime analysis of named arguments
|
|
//the type T is the actual formatted type and name is used only for lookup
|
|
//during runtime formatting
|
|
template<class T, class Char>
|
|
struct runtime_arg : public arg_base<T,Char>{
|
|
using char_type = Char;
|
|
using value_type = std::remove_cvref_t<T>;
|
|
};
|
|
|
|
//class used to store name and value for compile time analysis of named arguments
|
|
//the type T is the actual formatted type and Name is used for name lookup in
|
|
//format string checking
|
|
template<class T, rexy::cx::string Name>
|
|
struct static_arg : public arg_base<T,typename decltype(Name)::value_type>{
|
|
using char_type = typename decltype(Name)::value_type;
|
|
using value_type = std::remove_cvref_t<T>;
|
|
static constexpr auto static_name = Name;
|
|
|
|
constexpr static_arg(const T& v):
|
|
arg_base<T,char_type>{v, {Name.c_str(), Name.length()}}{}
|
|
static_arg(const static_arg&) = delete;
|
|
constexpr static_arg(static_arg&&) = default;
|
|
};
|
|
|
|
//temporary object to store Name to pass off to a compile time argument during assignment
|
|
template<rexy::cx::string Name>
|
|
struct arg_literal_result{
|
|
template<class T>
|
|
constexpr auto operator=(T&& t){
|
|
return static_arg<std::remove_cvref_t<T>, Name>{std::forward<T>(t)};
|
|
}
|
|
};
|
|
|
|
template<class T>
|
|
struct is_runtime_named_arg{
|
|
template<class U, class Char>
|
|
static auto check(runtime_arg<U,Char>) -> std::true_type;
|
|
static auto check(...) -> std::false_type;
|
|
|
|
static constexpr bool value = decltype(check(std::declval<std::remove_cvref_t<T>>()))::value;
|
|
};
|
|
template<class T>
|
|
static constexpr bool is_runtime_named_arg_v = is_runtime_named_arg<T>::value;
|
|
|
|
template<class T>
|
|
struct is_static_named_arg{
|
|
template<class U, rexy::cx::string Name>
|
|
static auto check(static_arg<U,Name>) -> std::true_type;
|
|
static auto check(...) -> std::false_type;
|
|
|
|
static constexpr bool value = decltype(check(std::declval<std::remove_cvref_t<T>>()))::value;
|
|
};
|
|
template<class T>
|
|
static constexpr bool is_static_named_arg_v = is_static_named_arg<T>::value;
|
|
|
|
template<class T>
|
|
concept RuntimeNamedArg = is_runtime_named_arg_v<T>;
|
|
template<class T>
|
|
concept StaticNamedArg = is_static_named_arg_v<T>;
|
|
|
|
template<class T>
|
|
concept NamedArg = StaticNamedArg<T> || RuntimeNamedArg<T>;
|
|
|
|
template<class It, std::size_t I, class Arg, class... Args>
|
|
constexpr std::size_t find_static_named_arg_id_impl(It first, It last);
|
|
template<class It, class... Args>
|
|
constexpr std::size_t find_static_named_arg_id(It first, It last);
|
|
|
|
template<class... Args>
|
|
struct count_named_args{
|
|
static constexpr std::size_t value = (std::size_t{NamedArg<Args>} + ...);
|
|
};
|
|
template<class... Args>
|
|
static constexpr std::size_t count_named_args_v = count_named_args<Args...>::value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|