如何从 `__func__` 中创建 `std::integer_sequence`?
How to create a `std::integer_sequence` out of `__func__`?
我正在尝试创建一个函数 foobar()
可以用作...
int main()
{
auto x = foobar(__func__);
// decltype(x) = std::integer_sequence<char, 'm', 'a', 'i', 'n'>
}
有什么提示吗?
代码不需要在 MSVC 上工作。
我看到的问题是将 __func__
作为函数参数传递
foobar(__func__);
我没有看到根据 __func__
的值更改 foobar()
的返回类型的方法。
如果将 __func__
作为模板参数传递,则不同,但 __func__
是字符串文字,并且字符串文字(据我所知)在 C++ 之前不能作为模板参数20.
但是...如果您接受将 __func__
作为模板参数传递的 C++20 解决方案...我想您可以编写如下内容
#include <utility>
#include <array>
template <std::size_t N>
struct bar
{
using index_type = std::make_index_sequence<N-1u>;
std::array<char, N-1u> arr;
template <std::size_t ... Is>
constexpr bar (std::index_sequence<Is...>, char const (&a0)[N]) : arr{a0[Is]...}
{ }
constexpr bar (char const (&a0)[N]) : bar{index_type{}, a0}
{ }
};
template <bar b, std::size_t ... Is>
constexpr auto baz (std::index_sequence<Is...>)
-> std::integer_sequence<char, b.arr[Is]...>
{ return {}; }
template <bar b>
constexpr auto foo ()
{ return baz<b>(typename decltype(b)::index_type{}); }
int main ()
{
using target_type = std::integer_sequence<char, 'm', 'a', 'i', 'n'>;
constexpr auto x = foo<__func__>();
static_assert( std::is_same_v<decltype(x), target_type const> );
}
这是使用 statement expression 语言扩展无需 C++20 即可与 GCC 和 Clang 一起工作的方法:
template<std::size_t n>
struct helper {
const char(& s)[n];
constexpr helper(const char(& str)[n]) : s(str)
{}
template<class Fn, std::size_t... is>
static constexpr auto apply(Fn fn, std::index_sequence<is...>) {
return fn(std::integral_constant<std::size_t, is>{}...);
}
template<class Fn>
static constexpr auto apply(Fn fn) {
return apply(fn, std::make_index_sequence<n - 1>{});
}
};
#define arr_as_char_sequence(ARR) \
({ constexpr helper my_helper(ARR); my_helper.apply([](auto... is) \
{ return std::integer_sequence<char, my_helper.s[is]...>{}; }); });
void foo() {
auto name = arr_as_char_sequence(__func__);
static_assert(std::is_same_v<
decltype(name), std::integer_sequence<char, 'f', 'o', 'o'>>);
}
我正在尝试创建一个函数 foobar()
可以用作...
int main()
{
auto x = foobar(__func__);
// decltype(x) = std::integer_sequence<char, 'm', 'a', 'i', 'n'>
}
有什么提示吗?
代码不需要在 MSVC 上工作。
我看到的问题是将 __func__
作为函数参数传递
foobar(__func__);
我没有看到根据 __func__
的值更改 foobar()
的返回类型的方法。
如果将 __func__
作为模板参数传递,则不同,但 __func__
是字符串文字,并且字符串文字(据我所知)在 C++ 之前不能作为模板参数20.
但是...如果您接受将 __func__
作为模板参数传递的 C++20 解决方案...我想您可以编写如下内容
#include <utility>
#include <array>
template <std::size_t N>
struct bar
{
using index_type = std::make_index_sequence<N-1u>;
std::array<char, N-1u> arr;
template <std::size_t ... Is>
constexpr bar (std::index_sequence<Is...>, char const (&a0)[N]) : arr{a0[Is]...}
{ }
constexpr bar (char const (&a0)[N]) : bar{index_type{}, a0}
{ }
};
template <bar b, std::size_t ... Is>
constexpr auto baz (std::index_sequence<Is...>)
-> std::integer_sequence<char, b.arr[Is]...>
{ return {}; }
template <bar b>
constexpr auto foo ()
{ return baz<b>(typename decltype(b)::index_type{}); }
int main ()
{
using target_type = std::integer_sequence<char, 'm', 'a', 'i', 'n'>;
constexpr auto x = foo<__func__>();
static_assert( std::is_same_v<decltype(x), target_type const> );
}
这是使用 statement expression 语言扩展无需 C++20 即可与 GCC 和 Clang 一起工作的方法:
template<std::size_t n>
struct helper {
const char(& s)[n];
constexpr helper(const char(& str)[n]) : s(str)
{}
template<class Fn, std::size_t... is>
static constexpr auto apply(Fn fn, std::index_sequence<is...>) {
return fn(std::integral_constant<std::size_t, is>{}...);
}
template<class Fn>
static constexpr auto apply(Fn fn) {
return apply(fn, std::make_index_sequence<n - 1>{});
}
};
#define arr_as_char_sequence(ARR) \
({ constexpr helper my_helper(ARR); my_helper.apply([](auto... is) \
{ return std::integer_sequence<char, my_helper.s[is]...>{}; }); });
void foo() {
auto name = arr_as_char_sequence(__func__);
static_assert(std::is_same_v<
decltype(name), std::integer_sequence<char, 'f', 'o', 'o'>>);
}