Suppose I have a class:
class MyClass{
char array[12];
public:
MyClass(const char* arr) {
for (int x = 0; x < 12; x++){
array[x] = arr[x];
}
}
};
Is it possible to make the MyClass
constructor constexpr
. The tricky part is initializing the new array....
I suppose (I hope) the following example could help.
I transformed your MyClass
in a templated class where the template parameter is the dimension of the array (12); I hope isn't a problem.
Should work with C++11 and C++14
#include <iostream>
template <std::size_t ...>
struct range
{ };
template <std::size_t N, std::size_t ... Next>
struct rangeH
{ using type = typename rangeH<N-1U, N-1U, Next ... >::type; };
template <std::size_t ... Next >
struct rangeH<0U, Next ... >
{ using type = range<Next ... >; };
template <std::size_t Dim>
class MyClass
{
public:
char array[Dim];
template <std::size_t ... rng>
constexpr MyClass (const char arr[Dim], const range<rng...> &)
: array{ arr[rng]... }
{ }
constexpr MyClass (const char arr[Dim])
: MyClass(arr, typename rangeH<Dim>::type())
{ }
};
int main ()
{
constexpr MyClass<12> mc1("0123456789a");
constexpr MyClass<37> mc2("0123456789abcdefghijklmnopqrstuvwxyz");
std::cout << mc1.array << std::endl;
std::cout << mc2.array << std::endl;
return 0;
}
p.s.: sorry for my bad English
--- edit: added C++14 example --
If you (when you) can use C++14, you can use std::index_sequence
and std::make_index_sequence
, avoiding range
and rangeH
.
The example become
#include <utility>
#include <iostream>
template <std::size_t Dim>
class MyClass
{
public:
char array[Dim];
template <std::size_t ... rng>
constexpr MyClass (const char arr[Dim],
const std::index_sequence<rng...> &)
: array{ arr[rng]... }
{ }
constexpr MyClass (const char arr[Dim])
: MyClass(arr, std::make_index_sequence<Dim>())
{ }
};
int main ()
{
MyClass<12> mc1("0123456789a");
MyClass<37> mc2("0123456789abcdefghijklmnopqrstuvwxyz");
std::cout << mc1.array << std::endl;
std::cout << mc2.array << std::endl;
return 0;
}
-- addendum: how to avoid explicit dimension indication --
If you find annoying count the char in a constant string, auto
is your friend; if you declare a constexpr
function in this way
template <std::size_t Dim>
constexpr MyClass<Dim> makeMyClass (const char (&arr)[Dim])
{ return MyClass<Dim> { arr }; }
you can declare your variables (or constants) of type MyClass<N>
in this way
constexpr auto mc1 = makeMyClass("0123456789a");
constexpr auto mc2 = makeMyClass("0123456789abcdefghijklmnopqrstuvwxyz");
instead
constexpr MyClass<12> mc1("0123456789a");
constexpr MyClass<37> mc2("0123456789abcdefghijklmnopqrstuvwxyz");
Works with C++14 and C++11 too.
You can use an std::array
instead of a C-array and everything just works:
#include <array>
class MyClass{
std::array<char, 12> array;
public:
constexpr MyClass(std::array<char, 12> arr) : array(arr){
}
};
int main() {
MyClass m({'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!'});
}
I don't know how to initialize the array with "Hello World!"
instead of that list of characters.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With