2017-06-11 21 views
2

私は循環バッファーライブラリを作成し始めました。私は特定の問題に出くわした:C++での一般的な循環バッファーの実装

template < class T > 
T CircularBuffer<T>::pop() 

それはタイプTを返しますが、事件について何CBが空で、ユーザーがポップアップを使用しようと()? nullptrを返すことは意味をなさない。なぜなら、nullptrは例えばdoubleに変換できないからである。明らかに、例外がスローされる可能性がありますが、それを行うより意味的にやさしい方法がありますか?

編集:

フルCBに押し、例外をスローするだけで自然である:「意味的に優しい」と私はこれが意味します。例外は、新しい要素に十分なメモリがないため、プログラムがクラッシュするのを防ぐ必要があります。空のCBをポップする際に例外を投げるのは、プログラムがクラッシュしそうにないので意味的に私には見えます。しかし、それが利用できる唯一の選択肢なら、教えてください。

+3

例外をスローすることについて意味的に不公平はありません。しかし、おそらく 'ポップ'を 'ポップ'と 'トップ'に分けるようにしましょう。したがって、「トップ」は現実的にスローされるが、それはノップになる可能性がある。また、削除時にコピーする必要がなくなり、いつもいいです。 – StoryTeller

+0

_ "明らかに、例外がスローされる可能性がありますが、もっと意味的にやりやすい方法がありますか?"とはどういう意味ですか?例外を投げることはおそらく唯一の有効なsemantcsです。また、 'std :: queue'がどのように問題を解決したかを調べるべきです。 'pop()'関数は 'void'を返し、一番上の要素は' front() 'を通してアクセスします。 –

+0

これは、最新のC++ 2017標準ライブラリをサポートするコンパイラを使用している場合、 'std :: optional'を置くことができる用途の1つです。 – Rook

答えて

1

これはstd::optionalまたはboost::optionalの完璧な使用例です。値はまたはの空の状態を格納するクラスです。

あなたがあなたの署名を変更することができます。

template < class T > 
std::optional<T> CircularBuffer<T>::pop() 

そして、あなたの契約はの線に沿って何かになります:バッファが空の場合、std::nulloptが返されます

  • それ以外の場合は、head要素を含む空でないstd::optional<T>が返されます。


また、ポップが成功した場合にのみ呼び出されますA「継続」機能を取ることを検討してください。例:あなたはまた、「ポップ失敗」の場合のための追加の継続を取ることによって、この概念を拡張することができ

some_circular_buffer.pop([](auto popped_item) 
{ 
    // I will only be called if the pop was successful. 
}); 

template < class F > 
decltype(auto) CircularBuffer<T>::pop(F&& continuation); 

使用。