2017-02-22 3 views
2

非可換の非コピー可能なクラスを非明示的なコンストラクタで使用している場合、返すことができます(C++ 11の場合):明示的なコンストラクタを使用してコピー不可能なオブジェクトを返す

#include <iostream> 
class NonCop 
{ 
public: 
    /*non explicit*/ NonCop(int a, int b) : number(a + b) {} 
    NonCop(const NonCop&) = delete; 
    int number; 
}; 

NonCop get_non_cop() 
{ 
    return {1, 2}; 
} 

int main() 
{ 
    NonCop &&nc = get_non_cop(); 
    std::cout << "three: " << nc.number << std::endl; 
    return 0; 
} 

ただし、コンストラクタが明示的な場合は機能しません。 NonCopに変更を加えずにC++ 11/C++ 14でこれを行う方法はありますか?

現在、私はNonCopからコンストラクタを "解説する"ラッパーを使って派生した回避策を使用していますが、それほど美しくはありません。

+1

[this](http://stackoverflow.com/questions/34263916/is-it-possible-to-return-an-instance-of-a-non-movable-non-copyable-type) C++のための11/14。 C++では、17の保証されたコピーelisionがコードをコンパイルすることに注意してください。 – NathanOliver

+0

私はそれが実際にうまくいくことをうんざりしており、また、あなたがこれをしたいと困惑しました。呼び出し側が同じオブジェクトを元に戻さないようにするのは非常にひどいことです。私はこれが単なる学問的な運動であり、あなたが実際にやりたいことではないことを願っています。 – Mehrdad

+0

@Mehrdad:C++ 03では、オブジェクトの有効期間をスコープの終わりまで拡張するconst参照に一時オブジェクトをバインドすることもできます。私はそれが愚かでスコープガードによって使われていると思う。 – knivil

答えて

1

不幸にも、このオブジェクトのコピーコンストラクターが最後にコピーされなくても、コンパイラーはオブジェクトのコピーコンストラクターにアクセス可能である必要があるため、一時オブジェクトを返すことはできません。ただし、具体的なオブジェクトの代わりにstd::unique_ptrを返すことができます。

std::unique_ptr<NonCop> get_non_cop() { 
    return std::make_unique<NonCop>(1, 2); 
} 

Live Demo

+0

ありがとう、私は知っているが、私はミューテックスロックのためにこれを必要とし、毎回追加割り当てを行うことは受け入れられない。 – peper0

+0

@ peper0:次に、実際のヒープアロケータを使用しないでください。プールアロケータなどを使用してください。 –

2

いいえ、これは不可能です。明示的なコンストラクタを呼び出すメカニズムはありませんが、C++ 11または14の関数から暗黙的な移動またはコピー(コンパイラが確実に無効になります)を返さずに戻ります。

C++では、return NonCop(1,2);と入力するだけで、 "elution保証"のため、移動コンストラクタやコピーコンストラクタは必要ありません。


しかしこれはC++なので、私はあなたのコードをゼロオーバーヘッドで動作させることができます。不正行為をし、別のタイプを返すことによって。

template<class T> 
struct implicit_construct:T { 
    template<class...Ts> 
    implicit_construct(Ts&&...ts): 
    T(std::forward<Ts>(ts)...) // note: this is an EXPLICIT construction 
    {} 
}; 

implicit_construct<NonCop> get_non_cop() 
{ 
    return {1, 2}; 
} 

Live exampleです。

implicit_construct<NonCop>NonCopから派生しているため、戻り値はNonCop&&に格納できます。

struct explicit_construct_t {}; 
// ... 
struct NonCop { 
    // ... 
    template<class...Ts> 
    NonCop(explicit_construct_t, Ts&&...ts): 
    NonCop(std::forward<Ts>(ts)...) 
    {} 
    // ... 
}; 

をあなたが暗黙的にそれらを呼び出すためにexplicit_construct_tでそれを付けることによって、明示的なコンストラクタを呼び出すことができることを意味:


あなたはNonCopを自分で書いている場合は、その後、私がやるだろうとするものを追加で

NonCop get_non_cop() { 
    return {explicit_construct_t{}, 1, 2}; 
} 
関連する問題