0

I can't pass a global cstyle array to a constexpr function for C++14. I have an array like this:

static const char t[] = "sometext";

And I have two functions:

template <typename T, typename U, std::size_t N>
constexpr static auto count(T (&arr)[N], const U &val)
{
    auto cnt = 0;
    auto it(std::cbegin(arr));
    while (it != std::cend(arr))
    {
        if (*it == val)
            cnt++;
        it++;
    }
    return cnt;
}

template <typename T, std::size_t N> constexpr static auto count_wrapper(T (&arr)[N])
{
    constexpr auto num_elems(count(arr, ','));
    return num_elems;
}

When I call the first function like that:

std::cout << count(t, ',') << std::endl;

I can compile the code and run it, but when I call the second function like that:

count_wrapper(t);

I get an error:

main.cpp: In instantiation of ‘constexpr auto t(T (&)[N]) [with T = const char; long unsigned int N = 46]’: main.cpp:51:53: required from here main.cpp:40:35: in constexpr expansion of ‘count((* & arr), ',')’ main.cpp:40:20: error: ‘arr’ is not a constant expression constexpr auto num_elems(count(arr, ',') + 1);

0

2 Answers 2

0

Arguments are not / cannot be constexpr. (constexpr functions might be used in non-constexpr context).

Notice that std::cout << count(t, ',') << std::endl; might be computed at runtime. you would need

constexpr auto c = count(t, ',');
std::cout << c << std::endl;

to have constexpr evaluation guarantee.

You might wrap the value in a type if appropriate.

template <typename T, T ... cs, typename U>
constexpr static auto count(std::integer_sequence<T, cs...>, const U &val)
{
    const T arr[] = {cs...};
    auto cnt = 0;
    auto it(std::cbegin(arr));
    while (it != std::cend(arr))
    {
        if (*it == val)
            cnt++;
        it++;
    }
    return cnt;
}

auto sometext = std::integer_sequence<char,
                                      's', 'o', 'm', 'e', 't', 'e', 'x', 't' /*, '\0'*/>;

constexpr auto num_elems(count(sometext, ','));
Sign up to request clarification or add additional context in comments.

Comments

0

What is num_elems? If it is fancy initialization, then whole code can be "rewritten" as this:

#include <cstdint>
#include <iterator>

const char t[] = "sometext";

template <typename T, typename U, std::size_t N>
constexpr auto count(const T (&arr)[N], const U &val)
{
    std::size_t cnt = 0;

    for(auto it = std::begin(arr); it != std::end(arr); ++it)
    {
        if (*it == val)
            cnt++;
    }

    return cnt;
}

template <typename T, std::size_t N> 
constexpr auto count_wrapper(const T (&arr)[N])
{
    auto const num_elems = count(arr, 'e');
    return num_elems;
}

int main()
{
    constexpr auto x = count_wrapper(t);
    return static_cast<int>(x);
}

This compiles and run correctly. I changed , to e so it counts some elements. I also changed while to for loop. Also I did changed auto cnt to std::size_t cnt.

Note because of auto, the type of x in main is size_t.

https://gcc.godbolt.org/z/3cdTzr

Comments

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.