在编译时生成简单格式字符串
Generating simple format string at compile time
我试图在编译时为 fmt 生成一个简单的格式字符串,但我不太明白字符串连接。我仅限于 c++ 14.
我想要的是能够为 N 项生成格式字符串,因此可以按如下方式使用:
auto my_string = fmt::format(format_string_struct<2>::format_string, "Item", "key1", "value1", "key2", "value2");
生成的格式字符串将是:“{} {}={} {}={}”,导致格式字符串为“Item key1=value1 key2=value2”。格式字符串的基础是“{}”,它为每个 N.
附加一个“{}={}”
我正在尝试使用递归模板,但我就是无法完全正常工作。我从 Concatenate compile-time strings in a template at compile time? 获得了一些用于连接字符串的代码(尽管我收到 undefined reference to `concat_impl<&base_format_string_struct::format_string, std::integer_sequence<int, 0, 1>, &format_string_parameter_struct::parameter_string, std::integer_sequence<int, 0, 1, 2, 3, 4, 5, 6, 7> >::value'
错误)
template<int...I> using is = std::integer_sequence<int,I...>;
template<int N> using make_is = std::make_integer_sequence<int,N>;
constexpr auto size(const char*s) { int i = 0; while(*s!=0){++i;++s;} return i; }
template<const char*, typename, const char*, typename>
struct concat_impl;
template<const char* S1, int... I1, const char* S2, int... I2>
struct concat_impl<S1, is<I1...>, S2, is<I2...>> {
static constexpr const char value[]
{
S1[I1]..., S2[I2]..., 0
};
};
template<const char* S1, const char* S2>
constexpr auto concat {
concat_impl<S1, make_is<size(S1)>, S2, make_is<size(S2)>>::value
};
struct base_format_string_struct {
static constexpr const char format_string[] = "{}";
};
struct format_string_parameter_struct {
static constexpr const char parameter_string[] = " {}=\"{}\"";
};
template <int arg_count, const char[]... params>
struct format_string_struct:
public format_string_struct<arg_count - 1, format_string_parameter_struct, params...> {
};
template <int arg_count>
struct format_string_struct:
public format_string_struct<arg_count - 1, format_string_parameter_struct> {
};
template <const char[]... params>
struct format_string_struct<0> {
static const char* format_string() {
return concat<base_format_string_struct, params...>;
}
};
您有几个拼写错误(并且一个 concat 限制为 2 个参数)。
template<int...I> using is = std::integer_sequence<int,I...>;
template<int N> using make_is = std::make_integer_sequence<int,N>;
constexpr auto size(const char*s) { int i = 0; while(*s!=0){++i;++s;} return i; }
template<const char*, typename, const char*, typename>
struct concat_impl;
template<const char* S1, int... I1, const char* S2, int... I2>
struct concat_impl<S1, is<I1...>, S2, is<I2...>> {
static constexpr const char value[]
{
S1[I1]..., S2[I2]..., 0
};
};
template<const char* S1, const char* S2, const char*... Ss>
struct concat
{
constexpr static const char* value = concat_impl<S1, make_is<size(S1)>, concat<S2, Ss...>::value, make_is<size(concat<S2, Ss...>::value)>>::value;
};
template<const char* S1, const char* S2>
struct concat<S1, S2>
{
constexpr static const char* value = concat_impl<S1, make_is<size(S1)>, S2, make_is<size(S2)>>::value;
};
struct base_format_string_struct {
static constexpr const char format_string[] = "{}";
};
struct format_string_parameter_struct {
static constexpr const char parameter_string[] = " {}=\"{}\"";
};
template <int arg_count, const char*... params>
struct format_string_struct:
public format_string_struct<arg_count - 1, format_string_parameter_struct::parameter_string, params...> {
};
template <int arg_count>
struct format_string_struct<arg_count>:
public format_string_struct<arg_count - 1, format_string_parameter_struct::parameter_string> {
};
template <const char*... params>
struct format_string_struct<0, params...> {
static const char* format_string() {
return concat<base_format_string_struct::format_string, params...>::value;
}
};
但我可能会使用 constexpr 函数:
#if 1 // missing some constexpr for std::array/std::copy
template <typename T, std::size_t N>
struct my_array
{
T data[N];
};
template <typename CIT, typename IT>
constexpr void copy(CIT begin, CIT end, IT dest)
{
for (CIT it = begin; it != end; ++it)
{
*dest = *it;
++dest;
}
}
#endif
template <std::size_t N>
constexpr my_array<char, 2 + 8 * N + 1> format_string_struct_impl()
{
my_array<char, 2 + 8 * N + 1> res{};
constexpr char init[] = "{}"; // size == 2
constexpr char extra[] = R"( {}="{}")"; // size == 8
copy(init, init + 2, res.data);
for (std::size_t i = 0; i != N; ++i) {
copy(extra, extra + 8, res.data + 2 + i * 8);
}
return res;
}
template <std::size_t N>
constexpr my_array<char, 2 + 8 * N + 1> format_string_struct()
{
// Ensure the computation is done compile time.
constexpr auto res = format_string_struct_impl<N>();
return res;
}
我试图在编译时为 fmt 生成一个简单的格式字符串,但我不太明白字符串连接。我仅限于 c++ 14.
我想要的是能够为 N 项生成格式字符串,因此可以按如下方式使用:
auto my_string = fmt::format(format_string_struct<2>::format_string, "Item", "key1", "value1", "key2", "value2");
生成的格式字符串将是:“{} {}={} {}={}”,导致格式字符串为“Item key1=value1 key2=value2”。格式字符串的基础是“{}”,它为每个 N.
附加一个“{}={}”我正在尝试使用递归模板,但我就是无法完全正常工作。我从 Concatenate compile-time strings in a template at compile time? 获得了一些用于连接字符串的代码(尽管我收到 undefined reference to `concat_impl<&base_format_string_struct::format_string, std::integer_sequence<int, 0, 1>, &format_string_parameter_struct::parameter_string, std::integer_sequence<int, 0, 1, 2, 3, 4, 5, 6, 7> >::value'
错误)
template<int...I> using is = std::integer_sequence<int,I...>;
template<int N> using make_is = std::make_integer_sequence<int,N>;
constexpr auto size(const char*s) { int i = 0; while(*s!=0){++i;++s;} return i; }
template<const char*, typename, const char*, typename>
struct concat_impl;
template<const char* S1, int... I1, const char* S2, int... I2>
struct concat_impl<S1, is<I1...>, S2, is<I2...>> {
static constexpr const char value[]
{
S1[I1]..., S2[I2]..., 0
};
};
template<const char* S1, const char* S2>
constexpr auto concat {
concat_impl<S1, make_is<size(S1)>, S2, make_is<size(S2)>>::value
};
struct base_format_string_struct {
static constexpr const char format_string[] = "{}";
};
struct format_string_parameter_struct {
static constexpr const char parameter_string[] = " {}=\"{}\"";
};
template <int arg_count, const char[]... params>
struct format_string_struct:
public format_string_struct<arg_count - 1, format_string_parameter_struct, params...> {
};
template <int arg_count>
struct format_string_struct:
public format_string_struct<arg_count - 1, format_string_parameter_struct> {
};
template <const char[]... params>
struct format_string_struct<0> {
static const char* format_string() {
return concat<base_format_string_struct, params...>;
}
};
您有几个拼写错误(并且一个 concat 限制为 2 个参数)。
template<int...I> using is = std::integer_sequence<int,I...>;
template<int N> using make_is = std::make_integer_sequence<int,N>;
constexpr auto size(const char*s) { int i = 0; while(*s!=0){++i;++s;} return i; }
template<const char*, typename, const char*, typename>
struct concat_impl;
template<const char* S1, int... I1, const char* S2, int... I2>
struct concat_impl<S1, is<I1...>, S2, is<I2...>> {
static constexpr const char value[]
{
S1[I1]..., S2[I2]..., 0
};
};
template<const char* S1, const char* S2, const char*... Ss>
struct concat
{
constexpr static const char* value = concat_impl<S1, make_is<size(S1)>, concat<S2, Ss...>::value, make_is<size(concat<S2, Ss...>::value)>>::value;
};
template<const char* S1, const char* S2>
struct concat<S1, S2>
{
constexpr static const char* value = concat_impl<S1, make_is<size(S1)>, S2, make_is<size(S2)>>::value;
};
struct base_format_string_struct {
static constexpr const char format_string[] = "{}";
};
struct format_string_parameter_struct {
static constexpr const char parameter_string[] = " {}=\"{}\"";
};
template <int arg_count, const char*... params>
struct format_string_struct:
public format_string_struct<arg_count - 1, format_string_parameter_struct::parameter_string, params...> {
};
template <int arg_count>
struct format_string_struct<arg_count>:
public format_string_struct<arg_count - 1, format_string_parameter_struct::parameter_string> {
};
template <const char*... params>
struct format_string_struct<0, params...> {
static const char* format_string() {
return concat<base_format_string_struct::format_string, params...>::value;
}
};
但我可能会使用 constexpr 函数:
#if 1 // missing some constexpr for std::array/std::copy
template <typename T, std::size_t N>
struct my_array
{
T data[N];
};
template <typename CIT, typename IT>
constexpr void copy(CIT begin, CIT end, IT dest)
{
for (CIT it = begin; it != end; ++it)
{
*dest = *it;
++dest;
}
}
#endif
template <std::size_t N>
constexpr my_array<char, 2 + 8 * N + 1> format_string_struct_impl()
{
my_array<char, 2 + 8 * N + 1> res{};
constexpr char init[] = "{}"; // size == 2
constexpr char extra[] = R"( {}="{}")"; // size == 8
copy(init, init + 2, res.data);
for (std::size_t i = 0; i != N; ++i) {
copy(extra, extra + 8, res.data + 2 + i * 8);
}
return res;
}
template <std::size_t N>
constexpr my_array<char, 2 + 8 * N + 1> format_string_struct()
{
// Ensure the computation is done compile time.
constexpr auto res = format_string_struct_impl<N>();
return res;
}