使用 C++ 模板定义函数,但显式删除它以防止滥用

Use a C++ template to define a function but explicitly delete it to prevent misuse

本文关键字:删除 C++ 定义 函数 使用      更新时间:2023-10-16

我有一个带有构造函数的模板类,我想在其中明确禁止使用定义良好的列表之外的任何类型的类型,如下所示:

template<typename Anything>
class MyClass
{
public:
MyClass(int &);
MyClass(float &);
MyClass(Anything &) = delete;
}

但是,由于整数双精度版本的代码是相同的,并且仅在类型上有所不同,因此我想使用模板化版本来定义它,例如:

template<typename Anything>
MyClass<Anything>::MyClass(Anything &var)
{
/* Code that operates over var */
...
}

而不是实际上必须复制两个有效构造函数的代码。

但是,当我尝试这样做时,我得到:

error: redefinition of 'MyClass<Anything>::MyClass(Anything&)'

它通过删除"= 删除">来工作。

有没有办法使用模板来定义函数,但不明确允许接收比显式描述的类型更多的类型?

我检查了如何防止函数模板中的隐式转换?以及为什么我可以阻止原语而不是用户定义类型的隐式转换?,但它们的问题似乎与当前问题不等同。

多谢。

更新:使用 gcc-4.8.5,它可以工作!!即使包含= delete关键字。

您的定义的问题在于您正在尝试实现您用= delete标记的确切功能。

您实际上想要另一个同时适用于intfloat的函数模板。您可以通过首先定义IntOrFloat谓词来实现这一点:

template <typename T>
using IntOrFloat = std::bool_constant<
std::is_same_v<T, int> || std::is_same_v<T, float>>; 

然后,您可以定义两个明确的构造函数,它们使用std::enable_if_t来检查谓词是否由用户传入的类型满足:

class MyClass
{
public:
template <typename T, 
std::enable_if_t<IntOrFloat<T>{}>* = nullptr>
MyClass(T&);
template <typename Anything, 
std::enable_if_t<!IntOrFloat<Anything>{}>* = nullptr>
MyClass(Anything&) = delete;
};

使用示例:

int main()
{
int v0 = 0;
float v1 = 0.f;
const char* v2 = "igijsdg";
MyClass x0{v0}; // OK
MyClass x1{v1}; // OK
MyClass x2{v2}; // Error
}

魔杖盒上的现场示例