模板实参推断与bind,ref总结

template <typename T> func(T arg)

  1. 模板形参没有任何引用,会忽略顶层const,比如传入const int,则T的参数仍为int
  2. 不会忽略底层const,比如传入const int* const,则T的参数为const int*
  3. 忽略引用

template <typename T> func(T& arg)

  1. 并不忽略顶层const,若传入const int&,则T为const int
  2. 若传入引用,将T推断为remove_reference
  3. 仅接受左值

template <typename T> func(const T& arg)

  1. 相比上者可传入右值,比如func(5),则T的类型为int

template <typename T> func(T&& arg)

  1. 俗称万能引用,T继承了arg原有的所有类型

bind与ref

先看一个代码片段

struct Sample
{
    int a = 1;
    void change(int &n)
    {
        n = 2;
    }
    function<void(void)> func = std::bind(&Sample::change, this, a);
};

template <typename T>
void g(T &&val)
{
}

int main(int argc, char **argv)
{
    Sample s;
    s.func();
    cout<<a<<endl;
    return 0;
}

结果不是2而是1,在cppreference中说到:The arguments to bind are copied or moved, and are never passed by reference unless wrapped in std::ref or std::cref.
如果std::bind(&Sample::change, this, std::ref(a))则会正常调用
查了下相关资料与reference_wrapper decay相关,暂时没有能力理解标准库代码。
注:往std::thread传入参数也是这样的道理