2016-05-25 16 views
4

下プリミティブ型の過負荷のために働いていません私はまた、次のものを持っていますAddOperatorもベースから継承する式のテンプレートは次のように私は<a href="https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern" rel="nofollow">CRTP</a>基本クラスを持って打ち鳴らす

template<typename TLhs, typename TRhs, size_t DIMS> 
struct AddOperator: public Base<AddOperator<TLhs, TRhs, DIMS>,DIMS> { 
    AddOperator(const TLhs& lhs, const TRhs& rhs) : lhs(lhs), rhs(rhs) { 
     print(rhs); 
    } 
    const TLhs &lhs; 
    const TRhs &rhs; 
}; 

その後Derivedタイプとプリミティブ型を返す種類の唯一のプロキシ/発現との間にoperator+オーバーロード:私はclangの下でこれを呼び出すとき

template<typename TLhs, typename TRhs, size_t DIM0, 
     typename std::enable_if<!std::is_arithmetic<TLhs>::value && 
           std::is_arithmetic<TRhs>::value,bool>::type = 0 > 
inline AddOperator<TLhs, TRhs, DIM0> 
operator+(const Base<TLhs,DIM0> &lhs, TRhs rhs) { 
    return AddOperator<TLhs, TRhs, DIM0>(lhs.self(), rhs); 
} 

は、しかし、私はAddOperatorrhsのためのごみ値を取得します。次に例を示します。

int main() { 

    Derived<double,2,2> g; 
    Derived<double,2,2> x = g+28; 

    return 0; 
} 

他のオーバーロードAddOperatorの両方のlhsrhsは、この問題を持っていないタイプDerivedであるとき。

この問題はclangの下でのみ発生します。 gccコンパイルされたコードが正常に動作しているようです。誰が問題がどこにあるか知っていますか?

Full Demo Here

答えて

6

あなたの問題は、あなたが宙ぶらりんの参照を持っているということです。

operator+には、値でTRhsint)を受け取り、それを参照してAddOperator<...>を作成します。 g+28が返された場合、AddOperator<...>オブジェクトにはパラメータrhsへの参照が残ります。寿命は現在終了しています。

印刷中のゴミは、破壊されたオブジェクトにアクセスした結果です。未定義の動作です。 clangでは、これはあなた自身のためにガベージ値を表示しているように見えますが、gccではうまく動作します。未定義の振る舞いはそれほど難しいです。今


、一見「明白な」修正はconstを参照してrhsを取るためにoperator+を変更することです。これにより、一時的な28の有効期間が呼び出しを含む完全な式の終わりまで延長されます。これで、あなたのprintステートメントは動作することが保証されます。少なくとも、行末まで。 xが構築された後、参照は再びぶら下がります。

+0

私は質問を投稿するとすぐに自分自身に気付きました。ありがとう –

関連する問題