将此ScopeExit类从代码项目中删除,但它不会构建在GCC 4.5.3上。感谢任何帮助。
class ScopeExit : private boost::noncopyable
{
typedef std::function<void()> func_t;
public:
ScopeExit(func_t&& f) : func(f) {}
~ScopeExit() { func(); }
private:
// no default ctor
ScopeExit();
// Prohibit construction from lvalues.
ScopeExit(func_t&);
// Prohibit new/delete.
void* operator new(size_t);
void* operator new[](size_t);
void operator delete(void *);
void operator delete[](void *);
const func_t func;
};
ScopeExit exit = [&]() { };
gcc 4.5.3错误:
In member function ‘void test()’:
error: conversion from ‘test()::<lambda()>’ to non-scalar type ‘ScopeExit’ requested
编辑:
ScopeExit exit([&]() { }); // this works
答案 0 :(得分:3)
这是复制/移动初始化。您的副本c-tor被删除,移动c-tor也被删除。
n3337 12.8 / 9
如果类X的定义没有显式声明移动构造函数,则将隐式声明一个 当且仅当
时默认为- X没有用户声明的复制构造函数
- X没有用户声明的复制赋值运算符
- X没有用户声明的移动赋值运算符
- X没有用户声明的析构函数,
- 移动构造函数不会被隐式定义为已删除。
不知道为什么第一种情况不起作用,但这种情况正常
template<typename T>
ScopeExit(T&& f) : func(std::move(f)) {}
ScopeExit(ScopeExit&& rhs) : func(std::move(rhs.func)) { }]
修改强>
当我们使用class-type变量的copy-initialization
时,只使用标准和elipsis隐式转换。从lambda转换为函数指针或从函数指针转换为std::function
为user-defined conversion
并且未使用。
n3337 8.5 / 16
初始化器的语义如下。目标类型是对象或引用的类型 初始化,源类型是初始化表达式的类型。如果初始化器不是单个(可能是 括号内的表达式,未定义源类型。
如果目标类型是(可能是cv限定的)类类型:
否则(即,对于剩余的复制初始化情况),用户定义的转换序列 可以从源类型转换为目标类型或(当转换函数时) (如果使用)对其派生类进行枚举,如13.3.1.4所述,最好的是 通过重载决议(13.3)选择。如果转换无法完成或模糊不清,那么 初始化是不正确的。
n3337 13.3.1.4/1
n3337 13.3.2在8.5中指定的条件下,作为类类型对象的复制初始化的一部分,由用户定义 可以调用转换以将初始化表达式转换为要初始化的对象的类型。 重载决策用于选择要调用的用户定义的转换。假设“cv1 T”是 正在初始化的对象的类型,使用T类类型,候选函数选择如下:
- T的转换构造函数(12.3.1)是候选函数。
- 在这两种情况下,参数列表都有一个参数,它是初始化表达式。 [注:这个论点 将与构造函数的第一个参数和隐式对象参数进行比较 转换函数。 - 结束说明]
1.从为给定上下文(13.3.1)构造的候选函数集中,有一组可行的函数 选择,通过比较参数的转换序列,从中选择最佳函数 最合适(13.3.3)。可行功能的选择考虑了参数和功能之间的关系 转换序列排名以外的参数。
第二,为了使F成为一个可行的函数,每个参数都应存在一个隐式转换。 quence(13.3.3.1)将该参数转换为F的相应参数。
n3337 13.3.3.1/4
但是,在考虑构造函数或用户定义的转换函数的参数时 当在类的第二步中复制/移动临时时,调用13.3.1.3的候选者 复制初始化,通过13.3.1.7将初始化列表作为单个参数或初始化时传递 list只有一个元素,并且转换为某个类X或引用(可能是cv-qualified)X 考虑到X的构造函数的第一个参数,或者在所有情况下由13.3.1.4,13.3.1.5或13.3.1.6考虑,仅 考虑标准转换序列和省略号转换序列。
答案 1 :(得分:1)
您通过将复制构造函数设为私有来禁止复制初始化(这是第一种情况下发生的情况)。但是你的构造函数ScopeExit(func_t&& f) : func(f) {}
是公共的,这就是在第二个(工作)声明中调用的内容。使用两个控制器的访问控制规范应该验证这一点。
编辑:ForEver错误的术语指出,有效 - ScopeExit(func_t&& f) : func(f) {}
不是移动构造函数。但这就是在第二种情况下被调用的内容,这就是它起作用的原因,而复制者的隐私就是第一种情况所不具备的原因。