2017-11-28 7 views
0

です:C++ 11右辺値のフィールドは、私はセットアップに多くのクラスのための移動のコンストラクタで使用するために、配列を交換するためのテンプレートをしようとしている右辺値

template <class T> void tools_swap_array(T* & a, T* & b) noexcept 
{ 
    auto tmp(a); 
    a = b; 
    b = tmp; 
} 

は、今私はそれを使用したいです)コンストラクタを移動しmove_from(と呼ばれる一般的な方法を介して代入演算子を移動:

valはクラスラベルのフィールドである
void label::move_from(label && ref) noexcept 
{ 
    tools_swap_array((char *)val, (char*)ref.val); 
} 

class label 
{ 
public: 
    // [...] 
    label(label && ref) { move_from(std::move(ref)); }; 
    label & operator = (label && ref) { move_from(std::move(ref)); return *this; }; 
    // [...] 
private: 
    char val[LABEL_SIZE]; 
}; 

しかし、私がコンパイラを実行すると、それはref.valがrvalueであることを伝えるmove_from()に失敗します

error: invalid initialization of non-const reference of type 'char*&' 
from an rvalue of type 'char*' 
tools_swap_array((char *)val, (char*)ref.val); 
              ^

私は、 "ラベル& & refは"(move_from内部左辺値になります)ので、 "ref.val" だろうと思いました。だから、私はまだrvalueへのC++ 11のリファレンスを誤解していますか、これはコンパイラのバグですか?

ありがとうございました!

+6

は[右辺値](HTTPを生成します。

#include <algorithm> template <class T, std::size_t N> void tools_swap_array(T (&a)[N], T (&b)[N]) noexcept { std::swap_ranges(a, a+N, b); } 

いずれかの方法で、あなたはこれを行うことができます'val'と同じアドレスを指す' char * '型の.com/w/cpp/language/value_category#rvalue)(一時オブジェクト)非const参照はrvaluesを参照することはできません。コンパイラは '(char *)ref.val'は' ref.val'ではなくrvalueであると言っています。 –

+4

残りの部分を除いて、2つのポインタを任意のサイズの配列の先頭にスワップしても、その配列はまったく変更されません。 – Deduplicator

+1

C++でプログラミングするときは、生ポインタを使用しないでください。これらはまれな例外的なケースのために予約されています。これはおそらくC++標準ライブラリの機能で既に解決されているでしょう。 – user0042

答えて

2

これを実装する正しい方法は、独自のスワップ関数をまったく書き込まないことです。 std::swap()はC++ 11以降では、使用する代わりに、例えば、固定サイズの配列のためのオーバーロードがあります。

#include <utility> 

void label::move_from(label && ref) noexcept 
{ 
    std::swap(val, ref.val); 
} 

あなたが本当に手動配列スワップ機能を実装したい場合は、あなたが実際に参照を渡す必要があります代わりに、それらへのポインタを渡すの配列、(単にポインタを交換すると、すべてので配列要素をスワップしない)、例えば:

#include <algorithm> 

template <class T, std::size_t N> 
void tools_swap_array(T (&a)[N], T (&b)[N]) noexcept 
{ 
    T tmp[N]; 
    std::copy_n(a, N, tmp); 
    std::copy_n(b, N, a); 
    std::copy_n(tmp, N, b); 
} 

または:

#include <utility> 

template <class T, std::size_t N> 
void tools_swap_array(T (&a)[N], T (&b)[N]) noexcept 
{ 
    for(std::size_t i = 0; i < N; ++i) 
     std::swap(a[i], b[i]); 
} 

か(これはESですsentially何std::swap())がない://en.cppreference: `(CHAR *)val`でキャスティング

void label::move_from(label && ref) noexcept 
{ 
    tools_swap_array(val, ref.val); 
} 
+0

レミーありがとうございます。私は最初にサイズ引数なしで自分のスワップテンプレートをセットアップしようとしました(引数として 'T(&a)[]'を使用していました)が、明らかに動作しません。私はポインタを使って試してみましたが、この値は私には驚きました。しかし、あなたは正しいです、自分のスワップメソッドを定義する必要はありません、私はstd :: swap oneを使用します。それを私に指摘してくれてありがとうと詳細な理由と私は自分のスワップテンプレートを実装する方法を持ってくれてありがとう:) –

関連する問題