c++string-literalsstring-viewemplace

Force decay of string literals (const char array) to ptr


In the following example I try to emplace_back() a string literal and a string_view into an std::pair of string_views. However, my problem is that emplace_back() takes up the string literal as a const char array and doesn't decay it to a pointer. The consequence is that emplace_back() can't find std::string_view's const char* constructor. How can I decay string literals manually as parts of function arguments (that are aggressively gobbled up by universal references)?

Demo

#include <utility>
#include <vector>
#include <string>
#include <string_view>
#include <cstdio>


struct A
{
    std::string_view vsn_ = "0.0.1";
    std::string_view key_;
};

auto get_url(A params = {})
{
    std::vector<std::pair<const char*, std::string_view>> queries;
    if (!params.key_.empty()) {
        queries.emplace_back(std::piecewise_construct, ("key="), params.key_);
    }
    if (!params.key_.empty()) {
        queries.emplace_back(std::piecewise_construct, ("VSN="), params.vsn_);
    }
    std::string url;
    for (auto q : queries) {
        
        url += q.first;
        url += q.second.data();
    }
    return url;
}

int main()
{
    printf("%s", get_url().data());
}

(As you can see I already tried to put parantheses around the string literals to no avail)


Solution

  • A std::piecewise_construct constructor (as you are trying to use here for the std::pair construction) expects the rest of the arguments to be std::tuples with each tuple holding the arguments to construct one of the pieces (e.g. pair elements).

    You are not passing tuples as second and third parameter, so it can't work. It should be

    queries.emplace_back(std::piecewise_construct,
                         std::forward_as_tuple("key="),
                         std::forward_as_tuple(params.key_));
    

    However, if you want construction of each pair element from just one argument, you don't need the piecewise constructor. std::pair has a constructor specifically for that:

    queries.emplace_back("key=", params.key_);
    

    None of this has anything to do with whether or not the array is decayed to a pointer. (It will be decayed where that is required, no manual intervention required.)