关于std::thread中的c++自动类型转换行为
Regarding C++ automatic type conversion behaviour in std::thread
我创建了两个类cl1
和cl2
, cl1
有一个构造函数,它接受cl2&
参数。我有三个函数,一个以cl1
为参数,一个以cl1&&
为参数,一个以cl1&
为参数。
#include <thread>
#include <iostream>
class cl1;
class cl2;
class cl2 {
public:
int y;
cl2(int y) : y(y) {} //ctor
};
class cl1 {
public:
int x;
cl1(int x) : x(x) {} //ctor
cl1(cl2& ob1) : x(ob1.y * 2) {} //ctor for automatic conversion of cl2& to cl1, x = y*2
};
void do_work_with_cl(cl1 ob) { //This works as usual by actually copying the object through the conversion constructor
std::cout << "The x of ob is " << ob.x << std::endl;
}
void do_work_with_cl_rref(cl1&& ob) { //I guess this works because it takes an rvalue and the automatic
//conversion ctor of cl1 does just that
std::cout <<"Inside the function that takes cl1 as rvalue, x of ob is" << ob.x << std::endl;
}
void do_work_with_cl_lref(cl1& ob) { //This doesn't work as ob is non-const lvalue reference
std::cout << "lvalue referenced but the object created through implicit conversion is temporary(i.e rvalue)" << std::endl;
}
int main() {
//Normal non-threaded calls
cl2 ob(100); //create a cl2 object
do_work_with_cl(ob); //This is ok
do_work_with_cl_rref(ob); //This too works
//do_work_with_cl_lref(ob) //This fails, as suspected
std::cout << "Thread part" << std::endl
//Now calling the functions through a thread
std::thread t1(do_work_with_cl_rref, ob); //Thought this could work here, but doesn't
//The other functions also don't work, but I can understand why.
t1.join();
}
在ideone.com: http://ideone.com/MPZc4C,当我要问这个问题时,这个例子是有效的。但是在g++-4.7中,我得到了如下错误:
In file included from /usr/include/c++/4.7/ratio:38:0,
from /usr/include/c++/4.7/chrono:38,
from /usr/include/c++/4.7/thread:38,
from main.cpp:1:
/usr/include/c++/4.7/type_traits: In instantiation of ‘struct std::_Result_of_impl<false, false, void (*)(cl1&&), cl2>’:
/usr/include/c++/4.7/type_traits:1857:12: required from ‘class std::result_of<void (*(cl2))(cl1&&)>’
/usr/include/c++/4.7/functional:1563:61: required from ‘struct std::_Bind_simple<void (*(cl2))(cl1&&)>’
/usr/include/c++/4.7/thread:133:9: required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(cl1&&); _Args = {cl2&}]’
main.cpp:13:44: required from here
/usr/include/c++/4.7/type_traits:1834:9: error: invalid initialization of reference of type ‘cl1&&’ from expression of type ‘cl2’
make: *** [main.o] Error 1
我真的不知道它是否有任何问题与实现,或代码…我只是在学习c++中的线程和东西,所以我这样做没有实际的原因。请让我知道问题是什么,如果我在代码的评论是正确的。(代码中的注释"This works…"意味着它们在以对象作为参数(而不是对它的引用)从main()调用时是好的)
c++标准第30.3.1.2/3段规定:
"要求:F和每个Ti in Args应满足MoveConstructible要求。INVOKE (DECAY_COPY(std::forward<F>(f)), DECAY_COPY(std::forward<Args>(args))...)
(20.8.2))必须是一个有效的表达式"。
表达式DECAY_COPY(x)
在30.2.6中定义:
"在这个子句的几个地方使用了DECAY_COPY(x)
操作。所有这些用法都意味着调用函数decay_copy(x)
并使用结果,其中decay_copy
定义如下:"
template <class T> typename decay<T>::type decay_copy(T&& v)
{ return std::forward<T>(v); }
由于decay
操作从对象中删除了cv限定符,因此需要有一个普遍有效的转换构造函数或从类型cl1
到类型cl2
的转换操作符。为了验证这一点,std::thread
的转发机制显然会生成对cl1
的右值引用,并试图从中获取c2
的实例。这是失败的,因为右值引用不能绑定到转换构造函数中的非const左值引用。
如果你将构造函数的签名从cl1(cl2& ob1)
更改为cl1(cl2 const& ob1)
,它可以在GCC 4.7.2中工作,因为右值引用可以绑定到左值引用到const
。
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- C++中的双指针类型转换
- 逐位操作的隐式类型转换
- 模板中的类型转换
- 在 C++(和 C)中进行类型转换时明显不一致
- 字符类型转换不兼容
- 将复杂的非基元C++数据类型转换为 Erlang/Elixir 格式,以使用 NIF 导出方法
- C++:用户定义的显式类型转换函数错误
- 将类指针类型转换为键时出错
- 通过引用传递参数时C++类型转换
- 在 C++ 中将一个模板类型的对象类型转换为另一个模板类型
- C++显式类型转换(C 样式强制转换)的强制表示法和static_cast的多种解释
- C++无效的函数类型转换
- 在将派生类指针类型转换为派生类指针后,从基类指针调用派生类函数
- 如何将Windows产品类型转换为名称?
- 通过构造函数方法输出的类到类类型转换是 5500 为什么不是 5555
- 事件系统:使用类型转换或联合进行继承
- 如何在参数中定义隐式类型转换的构造函数?
- 类模板实例化中的类型转换