Quest
Quest

Reputation: 2843

If constexpr ternary operator

I have a simple snipped below:

template<typename>
struct function_traits;

template<typename Rv, typename... Args>
struct function_traits<Rv(Args...)>
{
    static constexpr const char _signature[] = {GetTypeChar<Rv>, '(', GetTypeChar<Args>()..., ')', '\0'};
}

where GetTypeChar returns character representing a type (i for integer, d for double et cetra).
This works really well for simple types, eg function_traits<int(float,double)>::_signature returns i(f,d) as expected.

Now Imagine I would have the ability to see whether it is an array or not by adding '[]' after the array, eg double[] would result in d[].

I tried changing the signature to

static constexpr const char _signature[] = {GetTypeChar<Rv>(), '(', (std::is_array_v<Args> ? GetTypeChar<Args>(), '[', ']' : GetTypeChar<Args>())..., ')', '\0'};

but that seems to be completely ignored, and only things after : are evaluated.
Is something like this possible?

Upvotes: 2

Views: 324

Answers (1)

Quest
Quest

Reputation: 2843

Well, Initially I though I will be able to do this in a single array initialization, but the constexpr getter works well.
This is what I ended up with:

template<typename Tp>
constexpr void SetParamType(char*& dst)
{
    if constexpr (std::is_pointer_v<Tp>)
    {
        *dst++ = '[';
    }
    *dst++ = GetTypeChar<Tp>();
}

[[nodiscard]]
constexpr auto signature() const
{
    std::array<char, sizeof...(Args) * 2 + 4> out = {0};
    char * ptr = out.data();

    *ptr++ = GetTypeChar<return_type>();
    *ptr++ = '(';
    (SetParamType<Args>(ptr),...);
    *ptr++ = ')';
    *ptr++ = '\0';

    return out;
}

Please note that it would be wise to calculate the size of an array to exactly match the required length (which would not be hard after all, but for sake of simplicity I'll leave it as it is for now)

Upvotes: 1

Related Questions