2

I'm trying to create a function foobar() that can be used as...

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

Any hints?

The code does not need to work on MSVC.

10
  • C++ has very limited introspection capabilities. You're going to have to wait if this is exactly what you want. Commented Sep 29, 2020 at 20:05
  • 1
    The "macro" __func__ already expands to a constexpr "main". This isn't an introspection problem. Commented Sep 29, 2020 at 20:09
  • 2
    @max66 At least 14, given integer_sequence. Commented Sep 29, 2020 at 20:20
  • 1
    This appears to be a good option. Commented Sep 30, 2020 at 0:48
  • 1
    @cigien, thanks for the hint. It's working for me. Commented Sep 30, 2020 at 4:28

2 Answers 2

4

The problem I see is that passing __func__ as a function argument

foobar(__func__);

I don't see a way to change the returned type of foobar() according the value of __func__.

Different if you pass __func__ as template parameter, but __func__ is a string literal, and a string literal (as far I know) can't be a template parameter before C++20.

But... if you accept a C++20 solution where __func__ is passed as template parameter... I suppose you can write something as follows

#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> );
}
Sign up to request clarification or add additional context in comments.

Comments

1

Here is the approach that works with GCC and Clang without need for C++20 using the statement expression language extension:

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

1 Comment

Beautiful. I like it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.