2016-10-20 8 views
2

このイテレータの値を比較する2つのイテレータとカスタムコンパレータを必要とする関数が必要です。私はこれのために追加のテンプレート引数を使いたくない。このコードは、打ち鳴らすことにより、正常にコンパイルされていますが、GCC 5.4.0で、私はいくつかのエラーを持っているコンパレータを別のテンプレート関数に適切に渡す方法

template<typename T> 
void foo(T begin, T end, 
    function<bool(decltype(*begin), decltype(*begin))> compare = less<decltype(*begin)>()) 
{ 
    // I want to use 'compare' as: "compare(*begin, *begin);" 
} 

binary_heap.cpp:10:79: error: local variable 'begin' may not appear in this context 
    function<bool(decltype(*begin), decltype(*begin))> compare = less<decltype(*begin)>()) 
                      ^
binary_heap.cpp:10:85: error: template argument 1 is invalid 
    function<bool(decltype(*begin), decltype(*begin))> compare = less<decltype(*begin)>()) 

このコードを修正するためにどのように私はこの方法でそれを実装しましたそれはclangとGCCの両方でうまくコンパイルできますか?または、そのような関数を定義するためのより適切なソリューションがありますか?

+0

なぜ、このために追加のテンプレート引数を使用したくないのですか? – Yakk

答えて

5

デフォルトの引数にパラメータを使用することはできません。ただし、未評価のコンテキストであっても(この制限を緩和するためにStandardを修正する必要があります)。代わりにdecltype(*begin)の、

decltype(*std::declval<T&>()) 

編集使用:実は*演算子を適用すると、左辺値が得られた場合、その後、decltype指定子は左辺値参照に解決しますので、おそらく、あなたがやりたいことはありませんが、参照されていない型をstd::lessの引数にすることをお勧めします。より良い使用する:

typename std::iterator_traits<T>::value_type 

編集2:私はkrzaqに同意する、それだけで別のテンプレートパラメータを追加する方が良いでしょう。

4

function(詳細はhere)を強制するだけで、アルゴリズムのパフォーマンスを大幅に向上させることができます。ただ、テンプレートを取るCompareを推測し、あなたは黄金だ:

template<typename T, typename Compare = std::less<typename iterator_traits<T>::value_type>> 
void foo(T begin, T end, Compare compare = {}) 
{ 
    // I want to use 'compare' as: "compare(*begin, *begin);" 
} 

興味深いことに、標準アルゴリズムの力は、/の代わりにフォワーディング参照の値によってそれらをとることにより、軽量ファンクタの使用を示唆しています。あなたはstd::less<void>std::less<>、デフォルトを使用することができますし、実際の比較を行うoperator()テンプレート化しています:


は、実際の質問に答えるために

template<typename T> 
void foo(T begin, T end, 
    function<bool(decltype(*begin), decltype(*begin))> compare = less<>()) 
{ 
    // I want to use 'compare' as: "compare(*begin, *begin);" 
} 
+0

好奇心から、どのようにして 'function'を使ってパフォーマンスを悲観的にしていますか? – RyanP

+1

@RyanPは答えを編集しました – krzaq

+0

@krzaqありがとう!最高のパフォーマンスに関心があれば、私はどのような解決方法を選択すべきですか? – 0x1337

3

は、別のテンプレートパラメータCompareを追加します。これにより、コンパイラによるインライン化が容易になります。私はSentinelsをサポートしています。

template<class It, class Sentinel, class Compare=std::less<void>> 
void foo(It begin, Sentinel end, Compare cmp={}) { 
} 

しかし、C++ 14を想定して上記がなければ、私はこれを行うだろう:C++ 11で

template<class T> 
using comparator_sig = bool(T const&,T const&); 
template<class T> 
using comparator = std::function<comparator_sig<T>>; 
template<class It> 
using compare_inside_it = comparator< 
    typename std::iterator_traits<It>::value_type 
>; 

template<typename T> 
void foo(T begin, T end, compare_inside_it<T> compare = less<>) { 
} 

私はless<void>自分自身を記述します。

struct compare_less { 
    template<class T> 
    bool operator()(T const& lhs, T const& rhs) const { 
    return std::less<T>{}(lhs, rhs); 
    } 
}; 

およびdo:

template<typename T> 
void foo(T begin, T end, compare_inside_it<T> compare = compare_less{}) { 
} 

またはj ust do:

template<typename T> 
void foo(T begin, T end, compare_inside_it<T> compare = {}) { 
    if (!compare) compare=compare_less{}; 
} 
関連する問題