Reputation: 990
I'm looking to write a char buf wrapper that guarantees null-termination like the following:
template<size_t N> class BufStr
{
public:
explicit BufStr(const char(&buf)[N])
{
memcpy(m_buf, buf, N);
m_buf[N-1] = '\0';
}
inline const char* c_str() const { return m_buf; }
protected:
char m_buf[N];
};
But I'd like to use the signature template and be able to pass in a char buf directly to the constructor which would be able to determine the size of array using sizeof therefore computing N at compile time.
Upvotes: 3
Views: 138
Reputation: 14603
Try this:
template <typename T>
using buf_type = BufStr<::std::extent<T, 0>{}>;
int main()
{
char bla[] = "heh";
buf_type<decltype(bla)> buf(bla);
return 0;
}
Upvotes: 0
Reputation: 392893
Edited To account for the fact that you want to 'wrap' non-zero-terminated char arrays:
You could have a 'factory' function:
template <size_t N>
BufStr<N+1> make_bufstr(const char(&buf)[N])
{
return BufStr<N+1>(buf);
}
Demo (note the use of std::copy
instead of memcpy
):
#include <cstdint>
#include <algorithm>
template<std::size_t N> class BufStr
{
public:
explicit BufStr(const char(&buf)[N-1])
{
static_assert(N>0, "illegal size");
std::copy(buf, buf+N-1, m_buf);
m_buf[N-1] = '\0';
}
inline const char* c_str() const { return m_buf; }
protected:
char m_buf[N];
};
template <size_t N>
BufStr<N+1> make_bufstr(const char(&buf)[N])
{
return BufStr<N+1>(buf);
}
int main()
{
const char raw[] = { 'H', 'e', 'l', 'l', 'o' }; // no NUL termination!
auto s = make_bufstr(raw); // adds terminating NUL
}
Upvotes: 2