0

code as follows:

#include <iostream>
#include<functional>

class TestCase {
public:
    template<typename ...Args>
    void myfun(Args&& ...args) {
        sayhello(std::forward<Args>(args)...);
    }

private:
    void sayhello(const std::string& v, const std::string& v2) {
        std::cout <<" ---1---- " << v << "," << v2 << std::endl;
    }

};


template<typename ...Args>
void test(Args&& ...args) {
    TestCase a;
    auto f = std::bind(&TestCase::myfun<Args...>, &a,std::forward<Args>(args)...);
    f();
}


int main() {
    std::string a = "1";
    std::string b = "2";

    test(a,b);   //ok

    test("1","2");  //error
   
    return 0;
}

why std::forward not work? I tried pass value by lvalue and it work,but pass value by rvalue not work.I confused with TestCase::myfun<Args...> ,should it be TestCase::myfun<Args&&...> or something else?

cigien
  • 57,834
  • 11
  • 73
  • 112
  • 1
    "1","2" are not rvalues. They are pointers to C style arrays of chars. Try `test(std::string("1"), std::string("2"));` – doug Mar 10 '22 at 05:04
  • Is there any particular reason as to why you need to use std::bind()? If not, then you should be able to simply call myFun() like `a.myFun(std::forward(args)...);` – v.p. Mar 10 '22 at 06:25
  • oh,I have tried `test(std::string("1"), std::string("2"));` the same result happened. @doug – xudongxu Mar 10 '22 at 07:11
  • This is a example ,and confused me. I have replace `std::bind` with `lambda` ,and worked fine @v.p. – xudongxu Mar 10 '22 at 07:17

1 Answers1

1

The problem is similar to that in std::bind and rvalue reference.

std::bind will always copy the arguments and store them. When you use "1", "2", TestCase::myfun<Args...> is instantiated with Args = const char &[2], while the arguments are stored as const char * (due to the copy), so the error occurs since the parameter const char &[2] does not match arguments of const char *.

When you use std::string("1"), std::string("2"), TestCase::myfun<Args...> is instantiated with Args = std::string (so the parameter type is std::string &&). The error still occurs since the parameter std::string && does not match the stored arguments, which are lvalues.

As you have found, using lambda is a proper solution.

xskxzr
  • 12,442
  • 12
  • 37
  • 77
  • I have new question,I have a threadpool,inner impl uses std::bind;when I enqueue lambda in it,runs core dump,because params not existed. I must store the params first,then old problems reappears.Is exists right method to handle this? @xskxzr – xudongxu Mar 10 '22 at 10:44
  • I guess the problem comes from the call to `myfun`. You must call it with proper template arguments, or just leave the template arguments empty so they can be deduced by template argument deduction. I'm not sure without detailed codes. You can post a new question. – xskxzr Mar 11 '22 at 01:57