我正在玩Colvin-Gibbons在C ++ 03中实现移动语义的技巧,我得到了以下内容:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
template <typename T>
class buffer {
struct buffer_ref {
buffer_ref(T* data) : data_(data) {}
T* data_;
};
public:
buffer() : data_(NULL) {}
//explicit buffer(T* data) : data_(data) {}
buffer(size_t size) : data_(new T[size]) {}
buffer(buffer_ref other) : data_(other.data_) { other.data_ = NULL; }
buffer(buffer &other) : data_(other.data_) { other.data_ = NULL; }
~buffer() { delete [] data_; }
operator buffer_ref() { buffer_ref ref(data_); data_ = NULL; return ref; }
operator T*() { return data_; }
private:
T* data_;
};
int main() {
buffer<float> data(buffer<float>(128));
printf("ptr: %p\n", (float*)data);
}
修改:格式化
我希望能够在方便的时候使用我的缓冲区作为指向基类型的指针,所以我在指针类型中添加了一个转换操作符,它可以正常工作。但是,如果我取消注释带有指针的构造函数,那么转换推导会混淆并抱怨模糊转换(因为它可以转到缓冲区 - > T * - &gt;缓冲区或缓冲区 - &gt; buffer_ref-&gt;缓冲区) 。我希望指针构造函数上有一个显式修饰符来修复它,但事实并非如此。能理解C ++转换演绎的人比我更能解释编译器的想法吗?
答案 0 :(得分:2)
这是13.3.1.3 [over.match.ctor] 的直接结果:
当类类型的对象被直接初始化(8.5),或者从相同或派生类类型(8.5)的表达式中复制初始化时,重载决策选择构造函数。对于直接初始化,候选函数是正在初始化的对象的类的所有构造函数。对于复制初始化,候选函数是该类的所有转换构造函数(12.3.1)。 [...]
由于buffer<float> data(buffer<float>(128));
是直接初始化,因此您明确要求考虑explicit
构造函数。
如果你写:
buffer<float> data = buffer<float>(128);
然后没有歧义。