rexylib/include/rexy/detail/format/named_args.hpp

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