为什么 GCC 不给我一个错误
Why isn't GCC giving me an error
GCC 没有给我一个我希望它会出现的例子的错误:
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;
};
不使用复制构造函数时不会发生此错误(即使用复制构造函数时会发生)。
由于模板的原因,我不能简单地将复制构造器移动到代码文件中,然后在编译时失败。
我怎样才能让它失败?
这不是SFINAE,应该无法实例化模板。如果 copy-ctor 本身就是一个模板方法(比如说:
template<class U=T>
在上面那一行,那就是SFINAE。
我正在使用 GCC 4.8.1,-pedantic -Wall -Wextra
当然,-std=c++11
我希望通过以下方式让它失败:
int main() {
FirstVector<CannotBeCopied> whatever;
}
我知道 GCC 只是懒惰,不做不需要的工作,但我不喜欢这样,如果我在代码文件中显式实例化这个模板,我会得到一个错误。有没有办法得到我想要的错误?
如果您实际上没有创建模板的实例,则不需要调用复制构造函数 - 如果您不使用,甚至不会为 CannotBeCopied
创建模板代码它。调用拷贝构造函数会报错:
FirstVector<CannotBeCopied> a;
FirstVector<CannotBeCopied> b = a;
编辑:您还可以通过添加
来使用模板及其所有成员的显式实例化
template class FirstVector<CannotBeCopied>;
(语言规范§14.7.2)
C++ 中的模板仅在使用时具体化。
其他的都太贵了。
您可能听说过,C++ 模板是图灵完备的,因此评估它们可能非常昂贵。 IIRC 某处有一个 Fibonnaci<17> 的示例,它会让编译器计算这个数字...
特别是这意味着死代码将被消除,并且 c++ 编译器只会在您尝试使用复制构造函数时失败。
这不仅仅是 GCC 懒惰的问题;明确禁止按照标准执行您希望它执行的操作。 [temp.inst]/p1, 2, 11:
1 Unless a class template specialization has been explicitly
instantiated (14.7.2) or explicitly specialized (14.7.3), the class
template specialization is implicitly instantiated when the
specialization is referenced in a context that requires a
completely-defined object type or when the completeness of the class
type affects the semantics of the program. [...] The implicit instantiation of
a class template specialization causes the implicit instantiation of
the declarations, but not of the definitions, default arguments, or
exception-specifications of the class member functions [...]
2 Unless a member of a class template or a member template has been
explicitly instantiated or explicitly specialized, the specialization
of the member is implicitly instantiated when the specialization is
referenced in a context that requires the member definition to exist.
[...]
11 An implementation shall not implicitly instantiate a function
template, a variable template, a member template, a non-virtual member
function, a member class, or a static data member of a class template
that does not require instantiation.
这允许您拥有,例如,std::vector
s 仅移动类型。它们的复制构造函数不会编译,但只要你不使用它们,std::vector<std::unique_ptr<T>>
是完全有效的。
要强制它失败,您可以在 FirstVector
:
中使用 static_assert
static_assert(std::is_copy_constructible<T>::value, "T must be copy constructible");
但是请注意,这仅检查复制构造函数的声明是否可访问且未被删除,而不检查复制构造函数的主体是否会编译,这意味着它会错误地报告 std::vector<std::unique_ptr<T>>
是可复制构造的。
GCC 没有给我一个我希望它会出现的例子的错误:
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;
};
不使用复制构造函数时不会发生此错误(即使用复制构造函数时会发生)。
由于模板的原因,我不能简单地将复制构造器移动到代码文件中,然后在编译时失败。
我怎样才能让它失败?
这不是SFINAE,应该无法实例化模板。如果 copy-ctor 本身就是一个模板方法(比如说:
template<class U=T>
在上面那一行,那就是SFINAE。
我正在使用 GCC 4.8.1,-pedantic -Wall -Wextra
当然,-std=c++11
我希望通过以下方式让它失败:
int main() {
FirstVector<CannotBeCopied> whatever;
}
我知道 GCC 只是懒惰,不做不需要的工作,但我不喜欢这样,如果我在代码文件中显式实例化这个模板,我会得到一个错误。有没有办法得到我想要的错误?
如果您实际上没有创建模板的实例,则不需要调用复制构造函数 - 如果您不使用,甚至不会为 CannotBeCopied
创建模板代码它。调用拷贝构造函数会报错:
FirstVector<CannotBeCopied> a;
FirstVector<CannotBeCopied> b = a;
编辑:您还可以通过添加
来使用模板及其所有成员的显式实例化template class FirstVector<CannotBeCopied>;
(语言规范§14.7.2)
C++ 中的模板仅在使用时具体化。 其他的都太贵了。
您可能听说过,C++ 模板是图灵完备的,因此评估它们可能非常昂贵。 IIRC 某处有一个 Fibonnaci<17> 的示例,它会让编译器计算这个数字...
特别是这意味着死代码将被消除,并且 c++ 编译器只会在您尝试使用复制构造函数时失败。
这不仅仅是 GCC 懒惰的问题;明确禁止按照标准执行您希望它执行的操作。 [temp.inst]/p1, 2, 11:
1 Unless a class template specialization has been explicitly instantiated (14.7.2) or explicitly specialized (14.7.3), the class template specialization is implicitly instantiated when the specialization is referenced in a context that requires a completely-defined object type or when the completeness of the class type affects the semantics of the program. [...] The implicit instantiation of a class template specialization causes the implicit instantiation of the declarations, but not of the definitions, default arguments, or exception-specifications of the class member functions [...]
2 Unless a member of a class template or a member template has been explicitly instantiated or explicitly specialized, the specialization of the member is implicitly instantiated when the specialization is referenced in a context that requires the member definition to exist. [...]
11 An implementation shall not implicitly instantiate a function template, a variable template, a member template, a non-virtual member function, a member class, or a static data member of a class template that does not require instantiation.
这允许您拥有,例如,std::vector
s 仅移动类型。它们的复制构造函数不会编译,但只要你不使用它们,std::vector<std::unique_ptr<T>>
是完全有效的。
要强制它失败,您可以在 FirstVector
:
static_assert
static_assert(std::is_copy_constructible<T>::value, "T must be copy constructible");
但是请注意,这仅检查复制构造函数的声明是否可访问且未被删除,而不检查复制构造函数的主体是否会编译,这意味着它会错误地报告 std::vector<std::unique_ptr<T>>
是可复制构造的。