2016-11-28 13 views
0

C++で使い捨て変数を作成することはできますか?ここでC++には移動と削除のセマンティクスがありますか?

は私が達成したいものの一例である:ここで

const float _phiTemp = atan2(tan(cluster.beta), tan(cluster.alpha)); 
const float phi  = HALF_PI - std::abs(HALF_PI - std::abs(_phiTemp)); 
// After running this code I want _phiTemp to be unaccessible, and the 
// compiler to send an error if I ever try 

は、私が何をしたいの長いと醜い実装です:

const float phi = 0; 
{ 
    const float _phiTemp = atan2(tan(cluster.beta), tan(cluster.alpha)); 
    float& phiRef = const_cast<float&> phi; 
    phiRef = HALF_PI - std::abs(HALF_PI - std::abs(std::move(_phiTemp))); 
} 
// _phiTemp is disposed and phi is a const, and safely used in the calculation 
// through std::move() 

私は何かが足りないのですか? C++に「即時」の変数処分はありませんか?

+1

"* C++に"即時 "の変数処分はありませんか?*"あります。既にその例があります。スコープを示すには角かっこを使用し、スコープは寿命を示します。それについて醜いものはありません。 –

+0

まあ、瞬時には、 "現在のスコープでスタックから変数を取り除く"という意味です(+コンパイラが変数がなくなったことを知るようにします)。 –

+2

'phi'からconstをキャストし、それを使って代入すると未定義の振る舞いがあります。 – molbdnilo

答えて

6

長くて醜い実装も未定義の動作です。 phiRefへの書き込みはconstとして定義された変数への書き込みです。

あなたができる最善のは、phiを計算する関数を記述することです - あなたはこのインラインを行いたい場合は、ラムダを書くことができます:

const float phi = [&cluster]{ 
    const float phiTemp = atan2(tan(cluster.beta), tan(cluster.alpha)); 
    return HALF_PI - std::abs(HALF_PI - std::abs(phiTemp)); 
}(); 

...しかし、それはまだかなり醜いです。私はC++がこの機能を提供しているとは思わない。

+1

私は、IIFEラムダが短いコードのための最良のC++ 11ソリューションだと思います(これは私が実際のコードで使っているものです)。 pre-C++ 11およびより長いコードの場合は、単に別の名前付き関数を使用してください。 – KABoissonneault

0

Martin Bonnerは適切なトラックにあります:lambdaは "scope-with-return"としてうまく動作し、ここではヘルパー変数を好きなように宣言できます。以下は、私はさらに一歩それを取るために私の個人的なツールキットで作られたものです:

const float phi = glk_initBlock { 
    const float phiTemp = atan2(tan(cluster.beta), tan(cluster.alpha)); 
    return HALF_PI - std::abs(HALF_PI - std::abs(phiTemp)); 
}; 
+1

Eep!だからラムダを魔法の '演算子*'に渡して呼び出す(それを呼び出して結果を返す)。これは、ブロックの後に '()'が必要ないという点です。それは私を非常に巧妙なものにしています...でも、それが賢すぎるのかどうかはわかりません。 –

+0

...と私の答えの構文修正のおかげで! –

+0

@MartinBonner私はこのトリックの功績を認めていません - 私はAndrei Alexandrescuの「ScopeGuard」の話からそれを学びました。しかし、私はそれを愛しています:) – Quentin

-1

私が何をしたいことは、一時的な変数であると思う:

namespace initBlock_detail { 
    struct tag { }; 

    template <class F> 
    decltype(auto) operator * (tag, F &&f) { 
     return std::forward<F>(f)(); 
    } 
} 

#define glk_initBlock \ 
    glk::initBlock_detail::tag{} * [&]() -> decltype(auto) 

呼び出し構文は次のようになります。中間値の名前を付けないでください。

const float phi = HALF_PI - std::abs(
    HALF_PI - std::abs(
     atan2(
      tan(cluster.beta) 
      , tan(cluster.alpha) 
     ) 
    ) 
); 
+1

これはこの例では機能しますが(読みにくいですが)。 2番目の式が 'const float phi = 2 * square(_phiTemp)+ _phiTemp-1;'の場合(例えば、 –

+0

)これは2つの理由で失敗します。 1.計算を分離する目的を破り、 2.可読性を損なう 2.同じ変数をゼロから計算することなく再利用することはできません。 a * f(a)は、aを2回計算する必要があることを意味します。 –

+0

読みやすさの議論は主観的です。私は一度だけ使用される一時的な中間変数について特に読みやすいものは見つけられません。あなたが必要とする変数を宣言することは、2回目の場合と同じように、値を2度必要とするのが明白です。 – caps

関連する問題