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)?
#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)
CodePudding user response:
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::tuple
s 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.)