class my_class
{
...
my_class(my_class const &) = delete;
...
};
在这种情况下= delete是什么意思?
是否有其他“修饰符”(除了= 0和= delete)?
class my_class
{
...
my_class(my_class const &) = delete;
...
};
在这种情况下= delete是什么意思?
是否有其他“修饰符”(除了= 0和= delete)?
当前回答
删除的函数隐式内联
(现有答案的补充)
... 被删除的函数应该是函数的第一个声明(除了删除函数模板的显式专门化-删除应该在专门化的第一个声明处),这意味着您不能声明一个函数后再删除它,例如,在翻译单元的本地定义处。
引用(dcl.fct.def.delete) / 4:
删除的函数隐式内联。(注:一个定义 规则 ([basic.def.odr]) 适用于已删除的定义。- end note]删除的定义 函数的第一个声明应为函数或for 第一个是函数模板的显式特化 专门化的声明。(例子: 结构体sometype { sometype (); }; Sometype:: Sometype () = delete;/ /不规范的;非首次申报 - end示例)
删除了定义的主函数模板可以特殊化
Albeit a general rule of thumb is to avoid specializing function templates as specializations do not participate in the first step of overload resolution, there are arguable some contexts where it can be useful. E.g. when using a non-overloaded primary function template with no definition to match all types which one would not like implicitly converted to an otherwise matching-by-conversion overload; i.e., to implicitly remove a number of implicit-conversion matches by only implementing exact type matches in the explicit specialization of the non-defined, non-overloaded primary function template.
Before the deleted function concept of C++11, one could do this by simply omitting the definition of the primary function template, but this gave obscure undefined reference errors that arguably gave no semantic intent whatsoever from the author of primary function template (intentionally omitted?). If we instead explicitly delete the primary function template, the error messages in case no suitable explicit specialization is found becomes much nicer, and also shows that the omission/deletion of the primary function template's definition was intentional.
#include <iostream>
#include <string>
template< typename T >
void use_only_explicit_specializations(T t);
template<>
void use_only_explicit_specializations<int>(int t) {
std::cout << "int: " << t;
}
int main()
{
const int num = 42;
const std::string str = "foo";
use_only_explicit_specializations(num); // int: 42
//use_only_explicit_specializations(str); // undefined reference to `void use_only_explicit_specializations< ...
}
但是,不是简单地省略上面的主函数模板的定义,在没有显式特化匹配时产生模糊的未定义引用错误,而是可以删除主模板定义:
#include <iostream>
#include <string>
template< typename T >
void use_only_explicit_specializations(T t) = delete;
template<>
void use_only_explicit_specializations<int>(int t) {
std::cout << "int: " << t;
}
int main()
{
const int num = 42;
const std::string str = "foo";
use_only_explicit_specializations(num); // int: 42
use_only_explicit_specializations(str);
/* error: call to deleted function 'use_only_explicit_specializations'
note: candidate function [with T = std::__1::basic_string<char>] has
been explicitly deleted
void use_only_explicit_specializations(T t) = delete; */
}
产生可读性更强的错误消息,其中删除意图也清晰可见(未定义的引用错误可能导致开发人员认为这是一个不考虑周全的错误)。
回到为什么我们要使用这种技术?同样,显式专门化可以用于隐式地删除隐式转换。
#include <cstdint>
#include <iostream>
void warning_at_best(int8_t num) {
std::cout << "I better use -Werror and -pedantic... " << +num << "\n";
}
template< typename T >
void only_for_signed(T t) = delete;
template<>
void only_for_signed<int8_t>(int8_t t) {
std::cout << "UB safe! 1 byte, " << +t << "\n";
}
template<>
void only_for_signed<int16_t>(int16_t t) {
std::cout << "UB safe! 2 bytes, " << +t << "\n";
}
int main()
{
const int8_t a = 42;
const uint8_t b = 255U;
const int16_t c = 255;
const float d = 200.F;
warning_at_best(a); // 42
warning_at_best(b); // implementation-defined behaviour, no diagnostic required
warning_at_best(c); // narrowing, -Wconstant-conversion warning
warning_at_best(d); // undefined behaviour!
only_for_signed(a);
only_for_signed(c);
//only_for_signed(b);
/* error: call to deleted function 'only_for_signed'
note: candidate function [with T = unsigned char]
has been explicitly deleted
void only_for_signed(T t) = delete; */
//only_for_signed(d);
/* error: call to deleted function 'only_for_signed'
note: candidate function [with T = float]
has been explicitly deleted
void only_for_signed(T t) = delete; */
}
其他回答
删除的函数隐式内联
(现有答案的补充)
... 被删除的函数应该是函数的第一个声明(除了删除函数模板的显式专门化-删除应该在专门化的第一个声明处),这意味着您不能声明一个函数后再删除它,例如,在翻译单元的本地定义处。
引用(dcl.fct.def.delete) / 4:
删除的函数隐式内联。(注:一个定义 规则 ([basic.def.odr]) 适用于已删除的定义。- end note]删除的定义 函数的第一个声明应为函数或for 第一个是函数模板的显式特化 专门化的声明。(例子: 结构体sometype { sometype (); }; Sometype:: Sometype () = delete;/ /不规范的;非首次申报 - end示例)
删除了定义的主函数模板可以特殊化
Albeit a general rule of thumb is to avoid specializing function templates as specializations do not participate in the first step of overload resolution, there are arguable some contexts where it can be useful. E.g. when using a non-overloaded primary function template with no definition to match all types which one would not like implicitly converted to an otherwise matching-by-conversion overload; i.e., to implicitly remove a number of implicit-conversion matches by only implementing exact type matches in the explicit specialization of the non-defined, non-overloaded primary function template.
Before the deleted function concept of C++11, one could do this by simply omitting the definition of the primary function template, but this gave obscure undefined reference errors that arguably gave no semantic intent whatsoever from the author of primary function template (intentionally omitted?). If we instead explicitly delete the primary function template, the error messages in case no suitable explicit specialization is found becomes much nicer, and also shows that the omission/deletion of the primary function template's definition was intentional.
#include <iostream>
#include <string>
template< typename T >
void use_only_explicit_specializations(T t);
template<>
void use_only_explicit_specializations<int>(int t) {
std::cout << "int: " << t;
}
int main()
{
const int num = 42;
const std::string str = "foo";
use_only_explicit_specializations(num); // int: 42
//use_only_explicit_specializations(str); // undefined reference to `void use_only_explicit_specializations< ...
}
但是,不是简单地省略上面的主函数模板的定义,在没有显式特化匹配时产生模糊的未定义引用错误,而是可以删除主模板定义:
#include <iostream>
#include <string>
template< typename T >
void use_only_explicit_specializations(T t) = delete;
template<>
void use_only_explicit_specializations<int>(int t) {
std::cout << "int: " << t;
}
int main()
{
const int num = 42;
const std::string str = "foo";
use_only_explicit_specializations(num); // int: 42
use_only_explicit_specializations(str);
/* error: call to deleted function 'use_only_explicit_specializations'
note: candidate function [with T = std::__1::basic_string<char>] has
been explicitly deleted
void use_only_explicit_specializations(T t) = delete; */
}
产生可读性更强的错误消息,其中删除意图也清晰可见(未定义的引用错误可能导致开发人员认为这是一个不考虑周全的错误)。
回到为什么我们要使用这种技术?同样,显式专门化可以用于隐式地删除隐式转换。
#include <cstdint>
#include <iostream>
void warning_at_best(int8_t num) {
std::cout << "I better use -Werror and -pedantic... " << +num << "\n";
}
template< typename T >
void only_for_signed(T t) = delete;
template<>
void only_for_signed<int8_t>(int8_t t) {
std::cout << "UB safe! 1 byte, " << +t << "\n";
}
template<>
void only_for_signed<int16_t>(int16_t t) {
std::cout << "UB safe! 2 bytes, " << +t << "\n";
}
int main()
{
const int8_t a = 42;
const uint8_t b = 255U;
const int16_t c = 255;
const float d = 200.F;
warning_at_best(a); // 42
warning_at_best(b); // implementation-defined behaviour, no diagnostic required
warning_at_best(c); // narrowing, -Wconstant-conversion warning
warning_at_best(d); // undefined behaviour!
only_for_signed(a);
only_for_signed(c);
//only_for_signed(b);
/* error: call to deleted function 'only_for_signed'
note: candidate function [with T = unsigned char]
has been explicitly deleted
void only_for_signed(T t) = delete; */
//only_for_signed(d);
/* error: call to deleted function 'only_for_signed'
note: candidate function [with T = float]
has been explicitly deleted
void only_for_signed(T t) = delete; */
}
这是c++ 0x标准中的新功能,可以删除继承的函数。
= delete是c++ 11中引入的一个特性。由于per =delete,它将不允许调用该函数。
在细节。
假设在一个类中。
Class ABC{
Int d;
Public:
ABC& operator= (const ABC& obj) =delete
{
}
};
当调用这个函数进行obj赋值时,它将不被允许。表示赋值操作符将限制从一个对象复制到另一个对象。
= 0表示函数是纯虚函数,不能从该类实例化对象。您需要从中派生并实现此方法 = delete意味着编译器不会为你生成这些构造函数。AFAIK,这只允许在复制构造函数和赋值操作符上。但我不太擅长即将到来的标准。
新的c++ 0x标准。请参见N3242工作草案8.4.3