2013-10-02 6 views
5

私はboost :: to_lower_copyとstd :: transformを使用して文字列の束を小文字にしようとしています。以下のように、lamdbaを使って変種1が動作します。また、バリアント2は、コンパイラが選んだテンプレートのオーバーロードが正しいことを実証しています。しかしラムダはばかげています - それはboost :: to_lower_copyに沿って単一の引数を転送することだけです。しかし、私はそれをインスタンス化する場合でも、関数テンプレートを使用して、バリアント3は直接コンパイルされません。私は何が欠けていますか?変換するためにto_lower_copyをラムダでラップする代わりに直接渡すことができないのはなぜですか?

私はlibstdC++ - 4.8.1-1.fc19.i686とboost-1.53​​.0-14.fc19.i686を使って3.3のclang(タグ/ RELEASE_33/rc3)を持っています。

vector<string> strings = {"Foo", "Bar"}; 
vector<string> lower_cased_strings; 
transform(
    strings.begin(), 
    strings.end(), 
    inserter(lower_cased_strings, lower_cased_strings.end()), 
// Variant 1 
// [](const string &word) { 
//  return boost::to_lower_copy(word); 
// } 
// Variant 2 
// [](const string &word) { 
//  return boost::to_lower_copy<string>(word); 
// } 
// Variant 3 
    boost::to_lower_copy<string> 
    ); 

> clang++ -std=c++11 lowercase.cxx 

In file included from lowercase.cxx:3: 
In file included from /usr/include/boost/algorithm/string.hpp:18: 
In file included from /usr/include/boost/algorithm/string/std_containers_traits.hpp:23: 
In file included from /usr/include/boost/algorithm/string/std/slist_traits.hpp:16: 
In file included from /usr/lib/gcc/i686-redhat-linux/4.8.1/../../../../include/c++/4.8.1/ext/slist:47: 
In file included from /usr/lib/gcc/i686-redhat-linux/4.8.1/../../../../include/c++/4.8.1/algorithm:62: 
/usr/lib/gcc/i686-redhat-linux/4.8.1/../../../../include/c++/4.8.1/bits/stl_algo.h:4949:33: error: too few arguments to function call, expected 2, have 1 
     *__result = __unary_op(*__first); 
       ~~~~~~~~~~  ^
lowercase.cxx:11:5: note: in instantiation of function template specialization 'std::transform<__gnu_cxx::__normal_iterator<std::basic_string<char> *, std::vector<std::basic_string<char>, 
    std::allocator<std::basic_string<char> > > >, std::insert_iterator<std::vector<std::basic_string<char>, std::allocator<std::basic_string<char> > > >, std::basic_string<char> (*)(const std::basic_string<char> 
    &, const std::locale &)>' requested here 
transform(
^ 
+1

std :: bind()またはboost :: bind()で渡すようにしてください。 – Slava

+1

これもうまくいくでしょうが、lambdaとのバインドはIMOです。 –

答えて

5

デフォルト関数の引数。

boost::to_lower_copyには、3引数と2引数のバージョンがあります。インスタンス化している2引数のバージョンには、デフォルトの引数があります。したがって、直接呼び出されたときには、それを提供する必要はなく、暗黙的に提供されます。

しかし、to_lower_copyへの関数ポインタは、デフォルトの引数があるという事実をパッケージ化しません。

+1

@Slavaはい、そうです:[例](http://coliru.stacked-crooked.com/a/1136206601d880cc) – jrok

+0

ありがとう、TIL。デフォルトの引数をパッケージ化するクリーンな方法はありますか?私はバインドを使うことができたと思いますが、それは同じくらいぎこちないようです。またはラムダが最も醜い方法であるとあなたの裁判官になるでしょうか? –

+1

@AmbarishSridharanarayananちょうどラムダit。私の考えでは#2。そこにラムダが悩まされている場合、それがなぜそこにあるのかを示すコメントと共に( 'auto boost_to_lower = [] ...')行頭に置いてください。オーバーライドセットオブジェクトをC++に追加するという提案については続けることができますが、それはここでもそこにもありません。 – Yakk

関連する問題