0

次のような場合に適切な関数のオーバーロードを選択する正しい方法は何ですか?正しい関数のオーバーロードを選択するには?

#include <iostream> 
#include <algorithm> 

/** the correct overload **/ 
bool predicate(const char& c) 
{ 
    return c == '0'; 
} 

/** the wrong overload **/ 
template< typename CharType >  
bool predicate(const CharType& c, int some_other_parameters) 
{ 
    return c == '0'; 
} 

std::string 
process_string(const std::string& str) 
{ 
    std::string result; 
    std::copy_if(str.begin(), 
        str.end(), 
        std::back_inserter(result), 
        predicate); 

    return result; 
} 

int main() 
{ 
    std::cout << process_string("AK0NNDK0ASDAS0") << std::endl; 
    return 0; 
} 
+0

パラメータ数。 – knivil

答えて

3

ラムダを使用して述語のあいまい性を解決できます。

テンプレート以外のテンプレートがテンプレート機能よりも優先されることにも留意することも重要です。

また、関数ポインタをキャストすることもできます(ただし、これはもっと面倒です)。

std::copy_if(str.begin(), 
       str.end(), 
       std::back_inserter(result), 
       static_cast<bool(*)(const char&)>(&predicate)); 

Demo

ポインタキャストのバリエーションには、関数ポインタ型の入力と、必要な関数を指すローカル変数の取得があります。

using predicate_t = bool(*)(const char&); 
predicate_t my_predicate = &predicate; 
std::copy_if(str.begin(), 
       str.end(), 
       std::back_inserter(result), 
       my_predicate); 

Demo。優れている、それはサンプル外のコード、その場所(サードパーティのコード対すなわちあなたのコード)、あいまいなエラーの量、述語自体の複雑さに依存するオプションのところで


OPコードのような単純な条件が与えられた場合、ラムダはテスト自体を含むことができます。ラムダはこの場合非常に簡単です。

カウントが高い場合、より高いスコープ(ポインタ変換用のローカル変数を持つ)のusingバージョンが適切な場合があります。

「1回限り」の問題の場合は、static_castも問題ありません。たとえキャストが「外れている」と思われるとしても。

最終的には、おそらく個人的な好み(またはこの状況をカバーするものがあればガイドライン)によって最も影響を受けます。

ラムダは、さらに最近のauto&&といくつかの可変引数リスト、as seen in this answer in the linked questionと組み合わせることもできます。これらの現代技術がうまくいくことを念頭におく価値があります。ほとんどの現代のコンパイラは、この場合でもラムダをオプティマイズするので、その使用にはコストはかかりません(これは、ここのすべてのオプションに当てはまりますが、あくまであいまいさを解決します)。

理想的には、始めるにはあまりにも難しいはずがありませんが、それが起こり、私たちが見つけた文脈でできるだけ適切な方法で対処する必要があります。

+0

私はちょうど 'static_cast'答えを入力しました、それを加えるために+1します。これはラムダの貧弱な使用ですが、私はコンパイラがそれを排除することを願っています。 –

+0

これまでのところ、私はラムダの使用を時期尚早の悲観化と見ています。 –

関連する問題