std::bind 具有可变模板成员函数和通用引用
std::bind with variadic template member function and universal references
这里我有一小段代码,它可以编译并工作得很好
(至少对于我的 GCC 7.3.0 和 Ubuntu 18.04):
#include <functional>
#include <string>
#include <iostream>
void func(int a, const std::string& b, const std::string& c)
{
std::cout << a << b << c << std::endl;
}
class Test
{
public:
template <typename ... ARGS>
bool func_to_bind(ARGS&& ... args) const {
func(args...);
return true;
}
template <typename ... ARGS>
void binding_func(ARGS&& ... args) const
{
auto func_obj = std::bind(&Test::func_to_bind<int&, ARGS&...>, this, 42, args...);
func_obj();
}
};
int main()
{
Test obj;
obj.binding_func(std::string("one"), std::string("two"));
}
我不明白的部分是这一行:
std::bind(&Test::func_to_bind<int&, ARGS&...>, this, 42, args...);
为什么编译器要求使用引用作为模板类型参数?
如果我像这样从 int 中删除引用:
std::bind(&Test::func_to_bind<int, ARGS&...>, this, 42, args...);
它不会编译。另外,如果我将 func_to_bind 签名更改为:
bool func_to_bind(ARGS& ... args) const
即使缺少引用,它也能正常编译。
谁能解释这里到底发生了什么?
我也做了一些搜索,发现了这个问题:
How to combine std::bind(), variadic templates, and perfect forwarding?
但是我没有完全理解答案。
如果您明确指定模板参数为 int
,那么 func_to_bind
的参数类型将变为 int&&
,即右值引用类型。请注意,存储的参数通过 std::bind
:
作为 lvalues 传递给可调用对象
Otherwise, the ordinary stored argument arg is passed to the invokable object as lvalue argument:
左值无法绑定到右值引用参数,调用失败。
如果显式指定模板实参为int&
,则func_to_bind
的形参类型变为int&
,即左值引用类型;左值可以绑定到左值引用然后它工作正常。
并且如果将 func_to_bind
的参数类型更改为 ARGS&
,它将始终是左值引用,出于与上述相同的原因,它可以正常工作。
这里我有一小段代码,它可以编译并工作得很好 (至少对于我的 GCC 7.3.0 和 Ubuntu 18.04):
#include <functional>
#include <string>
#include <iostream>
void func(int a, const std::string& b, const std::string& c)
{
std::cout << a << b << c << std::endl;
}
class Test
{
public:
template <typename ... ARGS>
bool func_to_bind(ARGS&& ... args) const {
func(args...);
return true;
}
template <typename ... ARGS>
void binding_func(ARGS&& ... args) const
{
auto func_obj = std::bind(&Test::func_to_bind<int&, ARGS&...>, this, 42, args...);
func_obj();
}
};
int main()
{
Test obj;
obj.binding_func(std::string("one"), std::string("two"));
}
我不明白的部分是这一行:
std::bind(&Test::func_to_bind<int&, ARGS&...>, this, 42, args...);
为什么编译器要求使用引用作为模板类型参数? 如果我像这样从 int 中删除引用:
std::bind(&Test::func_to_bind<int, ARGS&...>, this, 42, args...);
它不会编译。另外,如果我将 func_to_bind 签名更改为:
bool func_to_bind(ARGS& ... args) const
即使缺少引用,它也能正常编译。 谁能解释这里到底发生了什么? 我也做了一些搜索,发现了这个问题: How to combine std::bind(), variadic templates, and perfect forwarding?
但是我没有完全理解答案。
如果您明确指定模板参数为 int
,那么 func_to_bind
的参数类型将变为 int&&
,即右值引用类型。请注意,存储的参数通过 std::bind
:
Otherwise, the ordinary stored argument arg is passed to the invokable object as lvalue argument:
左值无法绑定到右值引用参数,调用失败。
如果显式指定模板实参为int&
,则func_to_bind
的形参类型变为int&
,即左值引用类型;左值可以绑定到左值引用然后它工作正常。
并且如果将 func_to_bind
的参数类型更改为 ARGS&
,它将始终是左值引用,出于与上述相同的原因,它可以正常工作。