Reputation: 606
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);
Upvotes: 0
Views: 109
Reputation: 10539
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
Upvotes: 0
Reputation: 218098
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, ','));
Upvotes: 0