/**
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 .
*/
#ifndef REXY_DETAIL_FORMAT_NAMED_ARGS_HPP
#define REXY_DETAIL_FORMAT_NAMED_ARGS_HPP
#include //remove_cvref, declval, integral_constant
#include //forward
#include //size_t
#include "../../string_view.hpp"
namespace rexy::fmt{
namespace detail{
template
struct arg_base{
const T& value;
const basic_string_view 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
struct runtime_arg : public arg_base{
using char_type = Char;
using value_type = std::remove_cvref_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
struct static_arg : public arg_base{
using char_type = typename decltype(Name)::value_type;
using value_type = std::remove_cvref_t;
static constexpr auto static_name = Name;
constexpr static_arg(const T& v):
arg_base{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
struct arg_literal_result{
template
constexpr auto operator=(T&& t){
return static_arg, Name>{std::forward(t)};
}
};
template
struct is_runtime_named_arg{
template
static auto check(runtime_arg) -> std::true_type;
static auto check(...) -> std::false_type;
static constexpr bool value = decltype(check(std::declval>()))::value;
};
template
static constexpr bool is_runtime_named_arg_v = is_runtime_named_arg::value;
template
struct is_static_named_arg{
template
static auto check(static_arg) -> std::true_type;
static auto check(...) -> std::false_type;
static constexpr bool value = decltype(check(std::declval>()))::value;
};
template
static constexpr bool is_static_named_arg_v = is_static_named_arg::value;
template
concept RuntimeNamedArg = is_runtime_named_arg_v;
template
concept StaticNamedArg = is_static_named_arg_v;
template
concept NamedArg = StaticNamedArg || RuntimeNamedArg;
template
constexpr std::size_t find_static_named_arg_id_impl(It first, It last);
template
constexpr std::size_t find_static_named_arg_id(It first, It last);
template
struct count_named_args{
static constexpr std::size_t value = (std::size_t{NamedArg} + ...);
};
template
static constexpr std::size_t count_named_args_v = count_named_args::value;
}
}
#endif