2017-01-07 14 views
1

をテンプレートデフォルトのテンプレート引数の構文

template <typename ForwardIter, 
    typename Comp = std::less<typename std::iterator_traits<ForwardIter>::value_type>> 
void select_sort(ForwardIter first, ForwardIter last, Comp comp = Comp()) 
{ 
    for (; first != last; ++first) 
    { 
     auto iter = std::min_element(first, last, comp); 
     std::swap(*first, *iter); 
    } 
} 

と簡単なバージョン

template <typename ForwardIter, 
    typename Comp = std::less<>> 
void select_sort(ForwardIter first, ForwardIter last, Comp comp = Comp()) 
{ 
    // Same as above 
} 

間のいずれかの違いは、どちらも動作するようには思えあります。それはちょうどスタイルの問題ですか?あるいは、どちらか一方を選択する必要がある場合ですか?

答えて

2

どちらも機能しますが、それらは異なっています。

std::less<T>が最も一般的な使用例です。それはoperator()が過負荷になっているクラスです。これは、これと同様の方法で実装されています。

ここではポインタに関する特別なケースは省略していますが、簡単にするために単純な実装に過ぎません。

template<typename T> 
struct less { 
    constexpr bool operator()(const T &lhs, const T &rhs) const { 
     return lhs < rhs; 
    } 
}; 

これはファンクタのようなものですが、どちらを選択するかはTとなります。このソリューションの利点は、コードの特別な場合にstd::less<T>を特化できるということです。

std::less<>が異なります。 2つのタイプがoperator<でオーバーロードされている限り、どのタイプのオブジェクトでも比較できます。それは一般的なラムダのように機能します。あなたが見ることができるようにあなたがstd::less<>{}(a, b)を使用するときにa < bを書いたかのように

template<> 
struct less<void> { 
    template<typename T, typename U> 
    constexpr auto operator()(T&& lhs, U&& rhs) const 
      -> decltype(std::declval<T>() < std::declval<U>()) { 
     return std::forward<T>(lhs) < std::forward<U>(rhs); 
    } 
}; 

が、それは同じことに本当に近くだし、非constを持っているタイプでも動作します:少し、このように実装されていますoperator<。したがって、使用するクラスには、operator<がオーバーロードされている限り、この1つが最適です。

+0

それを得た。ありがとう。 – user515430

+1

完全性のために: 'std :: less ()'が同じ配列を指していないポインタ( '<'と違って)にも許される特別な例外は、 'std :: less <> 。あなたがこの答えに入れた定義は、それを正しく処理しません。(私はあなたが「ちょっと」のように書いたことを理解しています) – hvd

+0

@hvd私は答えを修正しました、指摘してくれてありがとう! –

2

typename Comp = std::less<typename std::iterator_traits<ForwardIter>::value_type>は、Compが指定されていない場合、std::less<typename std::iterator_traits<ForwardIter>::value_type>が使用されることを意味します。

typename Comp = std::less<>は、Compが指定されていない場合、std::less<>が使用されることを意味します。

正確には違います。これは、コンパイラが何らかの形でstd::less<>のテンプレート引数を推定することを意味するものではありません。代わりに、テンプレートstd::less<T=void>はデフォルト値を指定するため、そのデフォルト値が使用されます。

テンプレート特化std::less<void>は、一般に他のバージョンの代わりに使用できるように定義されています。それらはまったく同じものではなく、どちらか一方を使用するケースがあります。あなたの質問のタイトルから、あなたの質問は、具体的には約std::lessではなく、デフォルトの引数の構文についてのように見えるので、その説明は省略します。

+0

私が言うことができる限り、最初のスニペットはC++まで有効ではありません。14 –

+0

@EdgarRokyanこれはC++の現在のバージョンです。 (ちなみに、「第2のスニペット」を意味すると思います。) – hvd

+0

はい、間違いなく。私は今日の終わりに集中力を失ったようだ:) –

関連する問題