2017-12-26 23 views
2

は、次のコードを考えてみましょう:私は2つの質問持って呼び出すフリー関数を渡しますか?

void f(int) {std::cout << "void f(int)" << std::endl;} 
void f(double) {std::cout << "void f(double)" << std::endl;} 
void f(int*) {std::cout << "void f(int*)" << std::endl;} 
std::invoke(f, 3); 

:free関数(ないファンクタ)で

  • を、それがfの全体の過負荷セットを渡し、invokeは右を選択させることが可能です1? (ヘルパークラスなしで、それは純粋な言語の質問です)
  • void f(int)invokeに渡す方法はありませんか?コンパイラは、それが最善であるfのどの過負荷を把握するinvokeの実装を見ていない

    std::invoke(f, 3); 
    

    を解析するとき

+4

はい、適切なオーバーロードを選択するにはstatic_cast <>を使用する必要があります - https://stackoverflow.com/questions/24874478/use-stdbind-with-overloaded-functions – Slava

+0

@Vincent Try std: :(f、3)を呼び出します。 –

答えて

4

手動でオーバーロードセットを作成することをお勧めします。その後、

#define OVERLOADS_OF(name) [&](auto&&... args) -> decltype(name(FWD(args)...)) noexcept(noexcept(name(FWD(args)...))) { return name(FWD(args)...); } 

そして、これを渡します

invoke(OVERLOADS_OF(f), 3) 

この方法は、コンパイラは、まだ私たちのためのオーバーロードの解決をしている - 私たちはこれに自分自身を行う必要はありません - とintを取るオーバーロードがあります希望/期待通りと呼ばれる。

これは、意図した関数を直接渡すことと全く同じではないことに注意してください(例外的に浮動小数点型のオブジェクトを値で取り出す関数を含む)が、明示的な手動型の選択なしで可能です。

1

(数がある場合は、すべての可能な構文ものです)フィット。

したがって、fは、追加情報なしでコンパイラで解決することはできません。 fを適切な過負荷にキャスティングして追加情報を提供することができます。

std::invoke(static_cast<void(*)(int)>(f), 3); 
+0

static_cast (f) 'と' static_cast (f) 'には違いはありますか? – Vincent

+0

@Vincentは、このユースケースのためにはどちらかがうまくいくはずです。私は2つの間に大きな違いは見られません。 –

0

最初のテンプレート引数を明示的に指定できます。

std::invoke<void(int)>(f, 3); 

ここではデモンストレーションプログラムです。

#include <iostream> 
#include <functional> 

void f(int) {std::cout << "void f(int)" << std::endl;} 
void f(double) {std::cout << "void f(double)" << std::endl;} 
void f(int*) {std::cout << "void f(int*)" << std::endl;} 

int main() 
{ 
    std::invoke<void(int)>(f, 3); 
    std::invoke<void(double)>(f, 3); 
    std::invoke<void(int *)>(f, nullptr); 

    return 0; 
} 

その出力は

void f(int) 
void f(double) 
void f(int*) 

別のアプローチは、中間ポインタを使用することです。たとえば、

void (*pf)(int) = f; 
std::invoke(pf, 3); 
+0

これは悪い考えです。 ['std :: invoke']のすべてのテンプレート引数(http://en.cppreference。com/w/cpp/utility/functional/invoke)は、関数の引数から導かれ、完全な転送で使用されることを意図しています。テンプレートパラメータを指定すると、これが破られます。 STLの話[* Do not Help Compiler *](https://youtu.be/AKtHxKJRwp4)にこれが言及されています。 – Justin

+0

@Justin申し訳ありませんが、最初のテンプレート引数の指定が何を破るかはわかりません。 –

+0

@Justinまた、私の意見では、コードは最初の引数に静的なキャストを使うよりもきれいで読みやすいです。 –

関連する問題