How to compare int class template value?

I'm aware I should use std::string but this is question is about using template specialization a specific way.

I'm learning about template specialization and am thinking I can use it to design a templated wrapper class for c-strings. Call it CStr. One issue with c-strings I would like to focus on is that of string buffer allocation, copy construction and copy assignment.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// User-defined size; last character reserved for \0
#define MAX_CSTR_SIZE 100

struct CStr
{
    // Note: Buffer is zero-filled.
    CStr(void) 
    {
        cstr = new char[MAX_CSTR_SIZE];
        memset(cstr, 0, MAX_CSTR_SIZE);
    }

    // Construct a CStr from a c-string
    // Truncate-copy the c-string, up to MAX_CSTR_SIZE-1 chars.
    CStr(char *ptr) : CStr() 
    {
        strncpy(cstr, ptr, strlen(ptr));
    }  

    ~CStr()
    {
        free(cstr);
    }

    // Copy assignment
    CStr& operator=(CStr &rhs)
    {
        // This is definition is problematic if "this" cstring is default-constructed. The buffer is allocated 
        // but since it's zero-filled, strlen(this->cstr) and thus smallerSz will evaluate to 0. strncpy
        // will copy 0 bytes from rhs.cstr into this->cstr. In this case, copy the entire buffer of the smaller
        // of the two CStr types. 
        if (strlen(this->cstr) == 0) 
        {
            // Can't compare the size because it's not templated. So copy all MAX_CSTR_SIZE-1 bytes.
            strncpy(cstr, rhs.cstr, MAX_CSTR_SIZE-1); 
            cstr[MAX_CSTR_SIZE-1] = '\0';
            return *this
        }

        size_t smallerSz = std::min(strlen(cstr), strlen(rhs.cstr));
        strncpy(cstr, rhs.cstr, smallerSz); 
        return *this; 
    }
    
    char *cstr; 
};

bool operator!(const CStr& lhs, const CStr&rhs)
{
    if (!lhs.cstr || !rhs.cstr) return false;
    return strcmp(lhs.cstr, rhs.cstr);
}


Is there a way to create a templated version of CStr, specialized for int, so that CStr of different templated sizes can be assigned to one another? For example:

1
2
3
4
5
6
7
8
9
CStr<100> temp1 = {"World"}; 
CStr<50> temp2 = {"Hi"};
temp1 = temp2; // 100 > 50. No truncation. temp1 stores "Hi". 

temp1 = "World";
temp2 = "Hi";
temp2 = temp1; // 50 < 100. Truncate copy assign 49 bytes of temp1 into temp2's buffer. temp2 stores "Wo". 

CStr<75> temp3{temp1}; // 75 < 100. Truncate copy construct 


So above, temp1, temp2, temp3 are different types but their integer template value is used to determine whether truncation is used while performing string copies.
Last edited on
1) The default constructor can be:

 
CStr() : cstr(memset(new char[MAX_CSTR_SIZE], 0, MAX_CSTR_SIZE)) {} 



2) The constructor from a c-string should have a parameter of const char* and should be explicit. Also what happens if the length of the c-string is > MAX_CSTR_SIZE?

3) You haven't defined a copy constructor. (eg CStr(const CStr&) ). This is needed. An assignment is usually coded using the copy constructor. It would also be useful to define a move constructor and a move assignment.

4) As CStr is a struct, cstr should be marked private.

5) if (strlen(this->cstr) == 0) can be simplified to just !*cstr

6) You can pass a parametrised value to a class/struct and then access the value within the class/struct. Eg.

1
2
template<size_t sze = 100>
struct CStr {....}


where sze is the passed size (eg 50, 74, 100 etc) and defaults to 100 if none specified.
2. That's a good point. Only up to MAX_CSTR_SIZE-1 bytes will be copied.

3. Understood. Rule of 3. I defined it in my VS example but forgot to transcribe it over. It wasn't interesting - it just called the default ctor to perform the allocation.

4. Agreed. It was considered but I kept it public for convenience.

5. You're right!

6. Interesting. I will check if it's possible to define two size_t template arguments to perform the comparison.

 
template<size_t mySize, size_t otherSize> 
Registered users can post here. Sign in or register to post.