【问题标题】:Use a C++ template to define a function but explicitly delete it to prevent misuse使用 C++ 模板定义函数但显式删除它以防止误用
【发布时间】:2017-10-17 10:54:15
【问题描述】:

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

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

但是,由于 integerdouble 版本的代码是相同的,只是类型不同,我想使用模板化版本来定义它,如:

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

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

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

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

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

有没有一种方法可以使用模板来定义函数,但又不明确允许接收比明确描述的类型更多的类型?

我检查了How can I prevent implicit conversions in a function template?Why can I prevent implicit conversions for primitives but not user-defined types?,但他们的问题似乎与当前的问题不同。

非常感谢。

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

【问题讨论】:

  • 您的意思是让MyClass::MyClass(Anything) 成为模板,而不是整个班级?如果你只想禁用所有其他构造函数,你不应该模板整个类,只是那个构造函数。
  • MyClass(float &amp;); 应该是MyClass(double &amp;); 吗?您的问题提到 "... 整数和双精度版本 ...".
  • 通过一个更具体的例子,我们应该能够给你更好的建议。
  • 关于您的问题: 1.- 整个类都必须模板化,而不仅仅是构造函数,我还有其他成员也依赖于模板类型。 2.- 是的,它是浮动的,我的错字。

标签: c++ templates implicit-conversion deleted-functions


【解决方案1】:

您的定义的问题在于您正在尝试实现您用= 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
}

live example on wandbox

【讨论】:

  • std::bool_constantstd::integral_constant&lt;bool, Condition&gt; 的别名模板
  • 使用template &lt;typename T, std::enable_if_t&lt;cond&gt;* = nullptr&gt; 避免拥有Dummy = int
  • 感谢您的建议,两者都应用了。
猜你喜欢
  • 1970-01-01
  • 2022-01-14
  • 2021-06-15
  • 1970-01-01
  • 1970-01-01
  • 2021-06-08
  • 2018-10-23
  • 2010-11-27
相关资源
最近更新 更多