2

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

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&)'

它通过删除"= delete"起作用。

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

我检查了如何防止函数模板中的隐式转换?还有为什么我可以阻止基元而不是用户定义类型的隐式转换?,但他们的问题似乎并不等同于当前的问题。

非常感谢。

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

4

1 回答 1

3

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

int您实际上需要另一个同时适用于和的函数模板float。您可以通过首先定义一个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
}

wandbox 上的实时示例

于 2017-05-17T20:22:24.313 回答