如何从__func__中创建一个std :: integer_sequence`?

问题描述

我正在尝试创建可以用作...的功能foobar()

int main()
{
    auto x = foobar(__func__);
    // decltype(x) = std::integer_sequence<char,'m','a','i','n'>
}

有任何提示吗?

不需要在MSVC上运行该代码

解决方法

我看到的问题是将__func__作为函数参数传递

foobar(__func__);

我看不到一种根据foobar()的值来更改返回的__func__类型的方法。

如果您通过__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'>>);
}

Demo