Let's say I have this class:
template<int N>
class A {
public:
A(const char *s) ...
private:
const char buf[N];
};
The template is there so that I can configure the array size without dynamic memory allocation (a requirement). The buf
member is const
because it is intended to remain constant over the lifetime of the object after the object has been initialized.
To clarify, I also do not have access to the STL.
What are my options to define this constructor so that I can copy the contents of s
into buf
? One option is const_cast
but I'm looking for alternatives that does not require this.
The solution provided by @Richard Hodges requires the class be initialized with char array, as opposed to char const*
, which changes the signature of the constructor. If that doesn't work for your case, then here is one solution which does not change the signature:
template<int N>
class A
{
template<size_t...Is>
A(const char * s, std::index_sequence<Is...>)
: _assert(std::strlen(s) <= N, "size of buffer is bigger than N"),
buf{ (Is, *s != '\0'? *s++: *s)... }
{}
public:
A(const char *s) : A(s, std::make_index_sequence<N>()) {}
private:
throwable _assert;
const char buf[N];
};
where throwable
is defined as:
struct throwable
{
throwable(bool b, char const * message){
if (not b)
throw std::invalid_argument(message);
}
};
The use of throwable
ensures that buf
doesn't get initialized with buffer larger than N
bytes. If however your situation ensures that and thus doesn't need this check, you could remove it. The code should work without it as well, though I'd suggest you to keep it at least in debug mode.
Note that the addition of _assert
as member increases the size of the class at least by one byte. To avoid this, we could use empty base class optimiation and do this instead:
template<int N>
class A : private throwable
{
template<size_t...Is>
A(const char * s, std::index_sequence<Is...>)
: throwable(std::strlen(s) <= N, "size of buffer is bigger than N"),
buf{ (Is, *s != '\0'? *s++: *s)... }
{}
public:
A(const char *s) : A(s, std::make_index_sequence<N>()) {}
private:
const char buf[N];
};
That saves us 1 byte per instance.
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