8

私は現在、関数オブジェクトをチェーンしているライブラリに取り組んでいます。

呼び出し可能なオブジェクト(現時点ではstd :: function)を受け取り、関数の出力タイプと入力タイプでパラメーター化された関数テンプレートを作成しています。これが私が定義しているものの単純化されたバージョンです:

template <typename In, typename Out>
std::vector<Out> process(std::vector<In> vals, std::function< Out(In) > func)
{
    // apply func for each value in vals
    return result;
}

私が抱えている問題は使用法です。ラムダを渡すと、コンパイラーが型を正しく推測できないようです。そのため、関数が存在しないと文句を言います。

std::vector<string> strings;
// does NOT compile
auto chars = process(strings,
        []( std::string s ) -> char
        {
            return s[0]; // return first char
        }
);

ラムダを明示的にラップするstd::functionと、プログラムは次のようにコンパイルされます。

std::vector<string> strings;
// DOES compile
auto chars = process(strings,
        std::function< char(std::string) >(
        []( std::string s ) -> char
        {
            return s[0]; // return first char
        })
);

関数ポインターまたは関数オブジェクトの受け渡しはまだテストしていませんが、明示的なオブジェクトを直接渡さない場合、コンパイラーがパラメーターInとパラメーターを推測するのは難しいようです。Outstd::function

私の質問はこれです:これを回避する方法はありますか?それにより、呼び出しサイトで明示的に言及することなく、呼び出し可能なオブジェクトの入力/戻りタイプを推測できますか?

おそらく、入力/戻り型ではなく関数型でテンプレートをパラメーター化しますか?基本的に、任意の呼び出し可能オブジェクトのInとタイプを推測する必要があります。おそらく、テンプレート関数の戻り型のOutある種のauto/トリックですか?decltype

ありがとうございました。

4

2 に答える 2

9

あなたができることはdecltype、実際の関数オブジェクトに渡される引数を決定するために使用する中間の戻り値の型推定関数を作成することだと思います:

template <typename Out, typename In>
std::vector<Out> process_intern(std::vector<In> vals, std::function< Out(In) > func)
{
    // whatever
}

template <typename In, typename Func>
auto process(std::vector<In> vals, Func func) -> std::vector<decltype(func(vals[0]))>
{
    return process_intern<decltype(func(vals[0]))>(vals, func);
}

もちろん、process()関数型を型消去する理由がない限り、とにかくロジックを直接実装することを検討することをお勧めします。

于 2012-12-06T22:58:06.877 に答える
8

これを回避する方法はありますか?呼び出し可能なオブジェクトの入力/戻り値の型を呼び出しサイトで明示的に言及せずに推測できますか?

いいえ。ユーザー定義の変換は、テンプレートの引数推定では考慮されません。コンパイラは、パラメータの型と引数の型が (ほぼ) 正確に一致する必要があるように考え出さなければなりませんが、この場合は決して一致しませんInOut

おそらく、入力/戻り値の型ではなく、関数の型でテンプレートをパラメーター化します

はい、それが通常行われていることです (たとえば、標準ライブラリのアルゴリズムを見てください)。

于 2012-12-06T22:41:19.697 に答える