DEV Community

Horu
Horu

Posted on

Strings as template parameters (C++20)

First if we want to create a new type for a template parameter we need to create a structural type, this means we cannot use private members or functions.

Our compile time string will contain our string and it will not use new or delete, it can be possible to use new and delete in a constexpr function block but in this case we cannot hold dynamic memory in a lifetime constexpr variable.

I wrote the following template which it holds a fixed string, and can be used with templates as well.

#include <algorithm>

template<std::size_t N>
struct CompTimeStr {
    char data[N] {};

    consteval CompTimeStr(const char (&str)[N]) {
        std::copy_n(str, N, data);
    }

    consteval bool operator==(const CompTimeStr<N> str) const {
        return std::equal(str.data, str.data+N, data);
    }

    template<std::size_t N2>
    consteval bool operator==(const CompTimeStr<N2> s) const {
        return false;
    }

    template<std::size_t N2>
    consteval CompTimeStr<N+N2-1> operator+(const CompTimeStr<N2> str) const {
        char newchar[N+N2-1] {};
        std::copy_n(data, N-1, newchar);
        std::copy_n(str.data, N2, newchar+N-1);
        return newchar;
    }

    consteval char operator[](std::size_t n) const {
        return data[n];
    }

    consteval std::size_t size() const {
        return N-1;
    }
};

template<std::size_t s1, std::size_t s2>
consteval auto operator+(CompTimeStr<s1> fs, const char (&str) [s2]) {
    return fs + CompTimeStr<s2>(str);
}

template<std::size_t s1, std::size_t s2>
consteval auto operator+(const char (&str) [s2], CompTimeStr<s1> fs) {
    return CompTimeStr<s2>(str) + fs;
}

template<std::size_t s1, std::size_t s2>
consteval auto operator==(CompTimeStr<s1> fs, const char (&str) [s2]) {
    return fs == CompTimeStr<s2>(str);
}

template<std::size_t s1, std::size_t s2>
consteval auto operator==(const char (&str) [s2], CompTimeStr<s1> fs) {
    return CompTimeStr<s2>(str) == fs;
}
Enter fullscreen mode Exit fullscreen mode

This template will let us to operate over strings at compile time, we can compare and concatenate them at compile time.

Each time we concatenate strings it will return a new CompTimeStr<N>.

This lets us a world of possibilities, we could even create a search function to find specific words in our string and its position.

Usage example

This is a basic usage of CompTimeStr<N>

#include <iostream>

template<CompTimeStr str>
constexpr auto addBar() {
    return str + " bar";
}

constexpr CompTimeStr str = addBar<"foo">();

int main() {
    std::cout << str.data << std::endl;
    std::cout << std::boolalpha << (str == "foo bar") << std::endl;
}
Enter fullscreen mode Exit fullscreen mode

The output will be:

foo bar
true
Enter fullscreen mode Exit fullscreen mode

If we look at the non-optimized assembly output, we will find this:

Image description

We can see foo bar concatenated at compile time and (str == "foo bar") condition precalculated as well.

Top comments (1)

Collapse
 
denim06111991 profile image
denim06111991

Quite a well written article @sgf4

We are in the process of updating some books under our C++ portfolio. Over the next few weeks I am conducting a research in the C++ space to discover the top issues that C++ developers/programmers/experts like yourself are dealing with. We are reaching out to users to understand their needs/expectations and what they are looking for in C++ space.

After reviewing your profile, I believe that you could help me to gain a thorough understanding of what is working and not working for C++ developers like you.

Would you be happy to join me for a 10-minute call to discuss on how we can improvise our C++ books? Your inputs will be critical for us to bring forward a top-notch product for the C++ enthusiasts.