0

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)

2
  • Why the use of piecewise_construct? Commented Nov 25, 2022 at 18:25
  • Why are you using std::piecewise_construct? Just remove those and your code compiles. Commented Nov 25, 2022 at 18:25

1 Answer 1

2

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

Sign up to request clarification or add additional context in comments.

1 Comment

I guess I never really understood that till now thanks

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.