海湾合作委员会没有给我一个错误的例子我已经做了我希望它的例子:
class CannotBeCopied {
public:
CannotBeCopied(const CannotBeCopied&) = delete;
CannotBeCopied& operator=(const CannotBeCopied&) =delete;
CannotBeCopied() { }
~CannotBeCopied() { }
};
template<class T>
class FirstVector {
public:
FirstVector() {
size = 1;
data = new T[size];
}
~FirstVector() {
delete[] data;
}
FirstVector(const FirstVector& source) {
size = source.size;
data = new T[size];
for(int k=0;k!=size;k++) {
data[k] = source.data[k]; //<--I EXPECT AN ERROR HERE
}
}
private:
int size;
T* data;
};
当复制构造函数未使用时(即,在使用复制构造函数时确实发生),不会发生此错误。
由于模板,我不能简单地将copy-ctor移动到代码文件中,并在编译时失败。
我怎样才能让它失败?
这不是SFINAE,它不应该能够实例化模板。如果copy-ctor本身就是一种模板方法(比如说:
template<class U=T>
在上面一行,那就是SFINAE。
我正在使用GCC 4.8.1,当然-pedantic -Wall -Wextra
和-std=c++11
我希望通过以下方式解决这个问题:
int main() {
FirstVector<CannotBeCopied> whatever;
}
我知道GCC只是懒惰并且没有做它不需要的工作,但我不喜欢,如果我要在代码文件中显式实例化这个模板,我会收到错误。有没有办法得到我想要的错误?
答案 0 :(得分:3)
如果您实际上没有创建模板的实例,则不需要调用复制构造函数 - 如果您不使用它,则甚至不会为CannotBeCopied
创建模板代码。调用复制构造函数,您将收到错误:
FirstVector<CannotBeCopied> a;
FirstVector<CannotBeCopied> b = a;
编辑:您还可以通过添加
,使用模板的所有成员显式实例化模板template class FirstVector<CannotBeCopied>;
(语言规范的第14.7.2节)
答案 1 :(得分:3)
C ++中的模板仅在使用时实现。 其他一切都太贵了。
正如您可能已经听说的那样,C ++模板已经完成,因此评估它们可能会非常昂贵。 IIRC有一个Fibonnaci&lt; 17&gt;的某个例子,编译器可以计算这个数字......
特别是这意味着将删除死代码,并且只有在尝试使用复制构造函数时,c ++编译器才会失败。
答案 2 :(得分:1)
这不仅仅是海湾合作委员会的懒惰问题;肯定地禁止按照标准做你想做的事。 [temp.inst] / p1,2,11:
1除非已明确表示类模板特化 实例化(14.7.2)或明确专门化(14.7.3),类 模板特化是在隐式实例化的时候 在需要a的上下文中引用特化 完全定义的对象类型或类的完整性 type会影响程序的语义。 [...]隐式实例化 类模板特化导致隐式实例化 声明,但不是定义,默认参数或 类成员函数的异常规范[...]
2除非是类模板或成员模板的成员 显式实例化或明确专门化,专业化 当特化是隐式实例化成员的时候 在需要成员定义存在的上下文中引用。 [...]
11实现不应隐式实例化函数 模板,变量模板,成员模板,非虚拟成员 函数,成员类或类模板的静态数据成员 这不需要实例化。
这允许您拥有,例如std::vector
的仅限移动类型。他们的拷贝构造函数不会编译,但只要你不使用它们,std::vector<std::unique_ptr<T>>
就完全有效了。
要强制它失败,您可以在static_assert
内使用FirstVector
:
static_assert(std::is_copy_constructible<T>::value, "T must be copy constructible");
但是,请注意,这只会检查复制构造函数的声明是否可访问而不是删除,而不是复制构造函数的主体将编译,这意味着它将错误地报告std::vector<std::unique_ptr<T>>
是副本构造的。