2017-08-25 11 views
6

私はC++のテンプレートについて質問があります。次のコードはsegfaultsです。segfault in C++のテンプレート

template <typename T1, typename T2> 
inline T1 const& max(T1 const &a, T2 const &b) { 
    return a < b ? b : a; 
} 
int main() { 
    std::cout << max(4.9, 4) << std::endl; 
} 

ただし、&を削除しても問題はありません。

template<typename T1, typename T2> 
inline T1 const max(T1 const &a, T2 const &b) { 
    return a < b ? b : a; 
} 
int main() { 
    std::cout << max(4.9, 4) << std::endl; 
} 

さらに、T1とT2の代わりにTを使用しても問題ありません。

template<typename T> 
inline T const& max(T const &a, T const &b) { 
    return a < b ? b : a; 
} 

int main() { 
    std::cout << max(4, 5) << std::endl; 
} 

私はここで間違っていますか?

+0

使用しているバージョン番号など、どのコンパイラが記述されているかをご記入ください。それがGCCなら、 '-Wall'でコンパイルしましたか?無視している警告があり、未定義の動作が発生している可能性があります。 –

+0

コンパイラは、max()呼び出しが一時的な参照を返すことを通知する必要があります。 – tristan

+1

最初の2つのコードスニペットは同じですか? – asimes

答えて

10

警告は常にオンにしてコンパイルしてください。https://wandbox.org/permlink/KkhFOJw6QNJ7rv7Jを参照してください。警告フラグがオンになっていれば、コンパイラはあなたを助けて、あなたが何を間違っているのかを教えてくれました。

ここではプロモーション(Return type of '?:' (ternary conditional operator)を参照)があり、intdoubleで3者式を実行しています。その結果、一時的に昇格されますdouble。また、一時的な参照を返すと、その寿命が拘束された関数の後でそれを参照すると、未定義の動作になります。

1

2つ目は、まず一時的な参照を返します。

なぜですか?あなたの関数はタイプT1を返していますが、送信するタイプの1つを変換する必要があります。この変換により、一時的な正しいタイプが作成されます。それから戻ってきます。

一時的に死んでしまうので、返される参照は死んだオブジェクトにバインドされます。

修正プログラムが見つかりました。参照を返さないか、同じ型のパラメータを取るかのどちらかです。

標準の実装を見ると、同じタイプのパラメータを取るという2番目のソリューションが選択されています。