Elegantly concantenating std::string_view and string literal into a std::string

Assume I have the following function:

std::string greeting(const std::string_view name){
    return std::string(name) + " we wish you a very nice day and week and month and year";
}

It works fine, but I want to avoid more than 1 memory allocation, assuming name is too long to fit into SSO buffer. So I came up with this:

std::string greeting_efficient(const std::string_view name){
    constexpr std::string_view suffix = " we wish you a very nice day and week and month and year";
    std::string result;
    result.reserve(name.size()+suffix.size());
    result+=name;
    result+=suffix;
    return result;
}

AFAIK it works but it is quite ugly, is there a easier way to do this?

I am fine with using C++20/23 if solution needs it.

2 answers

  • answered 2022-05-04 10:47 WBuck

    You could use std::format which is a C++20 feature. Or you could pull in the fmt library which is what std::format is based off of if your compiler hasn't implemented std::format yet.

    #include <iostream>
    #include <format>
    #include <string>
    
    
    static std::string greeting(std::string_view name)
    {
        return std::format("{} have a very nice day", name);
    }
    
    int main() 
    {
        std::cout << greeting("Bill") << '\n';
    }
    

    You could also use an std::stringstream as well, but I'm unsure how efficient it is.

    static std::string greeting(std::string_view name) 
    {
        std::ostringstream os{};
        os << name << " have a very nice day";
        return os.str();
    }
    

  • answered 2022-05-04 10:47 Ted Lyngmo

    I'm not sure if it's more elegant or not, but this should assure that there's only one allocation:

    • Initialize the std::string with the correct size instead of default constructing it and reserving space. Expected effects:
      • (+) It makes the one allocation directly at construction.
      • (+) The string's internal size counter will not be changed in the rest of the process.
      • (-) It initializes the memory with the character of your choice.
    • Copy name directly into the string's memory.
    • Copy suffix directly into the string's memory.
      • Both copy operations needed should be using the fastest copying available. Two memcpys or memmoves will likely be the result.
    #include <algorithm>
    
    std::string greeting(std::string_view name){
        static constexpr std::string_view suffix = " we wish you a very nice day"
                                                   " and week and month and year";
    
        std::string rv(name.size() + suffix.size(), '\0'); // one allocation
    
        std::copy(suffix.begin(), suffix.end(),
                  std::copy(name.begin(), name.end(), rv.begin()));
    
        return rv;
    }
    

How many English words
do you know?
Test your English vocabulary size, and measure
how many words do you know
Online Test
Powered by Examplum