2016-08-24 6 views
2

私は、特定の方法で関数を呼び出すために純粋に構文上の目的のために使用するclassを持っています。これは簡単な例です:デストラクタを削除することで院内クラスができませんか?

#include<iostream> 

template<class T1> 
struct make{ 
    template<class T2> 
    static T1 from(T2 const& t2){ 
     return T1{}; //or something more complicated 
    } 
}; 

int main(){ 
    double d = make<double>::from(2); 
    std::cout << d << '\n'; 
} 

ここで、このクラスをインスタンス化しないように警告したいとします。 授業中に授業を行うことがあるかもしれませんが、 それを禁止することができるのであれば、私は好奇心を持っていますか?

まず私は、デフォルトコンストラクタ

template<class T1> 
struct make{ 
    make() = delete; 
    template<class T2> 
    static T1 from(T2 const& t2){ 
     return T1{}; //or something more complicated 
    } 
}; 

を削除しようとした。しかし、これはまだ可能です。最後に

make<double> m{}; // valid 

、私はデストラクタを削除しようと、それは

template<class T1> 
struct make{ 
    ~make() = delete; 
    template<class T2> 
    static T1 from(T2 const& t2){ 
     return T1{}; //or something more complicated 
    } 
}; 
を動作するように見えました

しかし、それでもクラスは0で割り振ることができるようです。

私は(何のコピーについてとコンストラクタを移動?)、デストラクタ、削除、コンストラクタの両方を削除する必要があります

これは、インスタンスを禁止するための最良の方法ですか?ここ コード:http://coliru.stacked-crooked.com/a/0299c377c129fffb

#include<iostream> 

template<class T1> 
struct make{ 
    make() = delete; 
    ~make() = delete; 
    template<class T2> 
    static T1 from(T2 const& t2){ 
     return T1{}; //or something more complicated 
    } 
}; 

int main(){ 
    double d = make<double>::from(2); 
    std::cout << d << '\n'; 
    make<double> m{}; // compile error (no destructor) 
    auto p = new make<double>{}; // compile error (no constructor) 
} 

答えて

3

しかし、これはまだ可能です:

make<double> m{}; // valid 

...私はそれが働くだろう知りませんでした。しかし、私は今、私も知っているそれが動作します。それで、それをやめる方法。

make<T>は集合体であると宣言したので動作します。削除された既定のコンストラクターがあるにもかかわらず、C++はそれを集約とみなします。また、集約でbraced-init-listsを使用すると、aggregate initializationが得られます。それを停止する

方法は簡単です:

template<class T1> 
struct make{ 
    template<class T2> 
    static T1 from(T2 const& t2){ 
     return T1{}; //or something more complicated 
    } 

    make() = delete; 

private: 
    char c; //Not an aggregate 
}; 

プライベートメンバ力make<T>それはもはや集約しないために:もはやそれ集約が作ります。したがって、集約初期化では使用できないため、{}はデフォルトコンストラクタの呼び出しを試みます。それは自然に削除されてから失敗します。

make<T>のインスタンスを作成するには、コピー可能な体操を使用することがあります。その型のオブジェクトを作成するから、法的なC++コードを防ぐのに十分であるべきだ

template<class T1> 
struct make{ 
    template<class T2> 
    static T1 from(T2 const& t2){ 
     return T1{}; //or something more complicated 
    } 

    make() = delete; 

private: 
    char c; //Not an aggregate 
    virtual ~make() = default; 
}; 

:あなたはそれをvirtualデストラクタを与えることによって、それらをシャットダウンすることができます。

+1

良い洞察力ですが、あなたのコードでこれはまだ許可されています: 'auto p = new make ;'、それはまだコンストラクタを削除する(またはプライベートにする)必要があるようです。 – alfC

+0

@alfC:私は構造を削除することを含めることを意味しました。それは単なるコピーアンドペーストエラーです。 –

+0

ok、コンストラクタとデストラクタが削除されたり、プライベート宣言されたりしたら、それを非agregateにすることで何を得るのですか? – alfC

関連する問題