stgtscc
stgtscc

Reputation: 990

Figure out array length statically using templates in C++

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

Answers (2)

user1095108
user1095108

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

sehe
sehe

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

Related Questions