简体   繁体   中英

No matching function for call std::forward(const std::string &) with variadic arguments

I'm trying to make a movable wrapper to non-copyable, non-movable class, however I have a problem passing a const std::string variable to the constructor. The minimal example below produces following error:

#include <iostream>
#include <memory>
#include <string>
#include <utility>

struct X {
    std::string x;

    X(const std::string &x) : x(x) {}
    X(const X &x) = delete;
    X(X &&x) = delete;
};

struct Wrapper {
    std::unique_ptr<X> x;

    Wrapper(const Wrapper & wrapper) = delete;
    Wrapper(Wrapper && wrapper) = default;

    template<typename... Args>
    Wrapper(Args&&... args) : x(std::make_unique<X>(std::forward(args)...)) {}
};

int main() {
    const std::string XXX = "XXX";
    Wrapper w{XXX};
    std::cout << w.x->x << std::endl;
}

Error message here:

forwarding.cc:21:53: error: no matching function for call to 'forward'
    Wrapper(Args&&... args) : x(std::make_unique<X>(std::forward(args)...)) {}
                                                    ^~~~~~~~~~~~
forwarding.cc:26:13: note: in instantiation of function template specialization 'Wrapper::Wrapper<const std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > &>' requested here
    Wrapper w{XXX};
            ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/../../../../include/c++/7.2.0/bits/move.h:73:5: note: candidate template ignored: couldn't infer template argument '_Tp'
    forward(typename std::remove_reference<_Tp>::type& __t) noexcept
    ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/../../../../include/c++/7.2.0/bits/move.h:84:5: note: candidate template ignored: couldn't infer template argument '_Tp'
    forward(typename std::remove_reference<_Tp>::type&& __t) noexcept
    ^
1 error generated.

You need to explicitly pass template parameters to std::forward :

std::forward<Args>(args)...

This is because std::forward needs some way of knowing the "original value category" of args... , which is impossible through template argument deduction alone as args is always an lvalue.

Lvalues will deduced as lvalue references in the context of template argument deduction for forwarding references (as a special rule), so std::forward can do its job by looking at the types inside Args... .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM