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

112 Views Asked by At

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)

1

There are 1 best solutions below

1
user17732522 On BEST ANSWER

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.)