2017-03-15 14 views
2

私は最近、C++ 17標準に導入されるstd::is_invocableを見つけました。なぜなら、なぜユーザにタイプを提供する必要があるのでしょうか?特に非型のテンプレートパラメータが今や拘束されることができないので、より便利かもしれない関数ポインタ自体を提供するのではなく、なぜstd :: is_invocableが非タイプのテンプレートパラメータを受け入れるのではない

std::is_invocableため

void hello_world() { 
    cout << "Hello world" << endl; 
} 
int main() { 
    cout << std::is_invocable_v<decltype(hello_world)> << endl; 
    // as opposed to being able to do 
    // cout << std::is_invocable_v<hello_world> << endl; 

    return 0; 
} 
+0

テンプレートパラメータとして関数ポインタを渡すと、チキンと卵の問題が発生するので、http://stackoverflow.com/questions/1174169/function-passed-as-template-argumentを参照してください(これを感じないでください)。実際には二重である)。関数の型を最初のテンプレートパラメータとして定義する必要がありますが、そのためには残りのテンプレートパラメータが必要です。 –

+0

1つはタイプであり、もう1つは値です。 –

+1

@SamVarshavchik Dude、何言ってるの? C++ 17、 'template auto'です。 – Barry

答えて

4

私は疑問に思って:今、あなたはそのようなcallF機能を使用することができます便利

あなた常には、テストしたいことを呼び出し可能なの種類を持っていますが、あなたは常にCONSTとしてのを持っていないのでアリの表現。確かに、値があるときはfooの代わりにdecltype(foo)を書き出す必要がありますが、これはかなり軽微な負担のように思えますし、ユースケースのかなりの割合を占めるでしょう。 template <auto F, class... Args> is_invocableを追加しただけの複雑さに匹敵する価値があるかどうかはわかりません。そのため、ユーザーがdecltypeを書く必要はありません。

3

主な用途以下の例で説明することができる私は何を意味種類とテンプレートパラメータを使用することです。関数ポインタを直接使用するだけでは使用できない。

はのは、あなたのコードビットを変更すると便利なケースを追加してみましょう:

void callF(F function, Args&& args) { 
    std::invoke(function, std::forward<Args>(args)...); 
} 

// Later, in your main 

callF(hello_world); 

あなたが呼び出しコールが無効になるとき呼び出し可能でないためにあなたの機能をフィルタリングしたいと思います。あなたはちょうどそのようstd::is_invokableを使用することができます:あなたが見ることができるように

auto callF(F function, Args&& args) -> std::enable_if<std::is_invocable_v<F, Args...>> { 
    std::invoke(function, std::forward<Args>(args)...); 
} 

std::is_invocableに引数として送ら種類がstd::invokeに送信された引数を反映しています。

ボーナスとして、関数ポインタ以上の機能がサポートされています。関数オブジェクトもサポートされており、メンバ関数ポインタもサポートされています。それは、ユーザーが必要とする理由ちょうどより多くであるかもしれない関数ポインタ自体を提供することとは対照的に、関数ポインタの型を提供するために、

callF([](int i){ /* ... */ }, 8); 

struct Test { void test() {} }; 

Test t; 

callF(&Test::test, t); 
関連する問題