2016-06-16 7 views
1

なぜC++ 11では以下のコンパイルが行われますか? (私はそれがリンクされないことを知っています)1()は関数型ではないので、私はstd::enable_ifテストが失敗すると期待しています。std :: enable_if引数は関数ですか?

+0

はあなたでしょう正しく使用する方法を書き留めておきますか?または私にリンクを教えてください? – oconnor0

+1

正確にSFINAEに何をしようとしていますか? –

+0

私は、 'Func'が' Args ... 'に適用できる関数(できれば関数ポインタ)であるときに' delegate'を呼び出し可能にしようとしていました。私は最初のパラメータの型として 'Func *'を使いたいと思っています。 – oconnor0

答えて

6
#include <type_traits> 

template <typename Func, typename... Args> 
typename std::enable_if<std::is_function<Func(Args...)>::value>::type 
    delegate(Func, Args...); 

int main(void) { 
    delegate(1); // << Why does this line compile? 
    return 0; 
} 

FuncArgsが空であるので、Func(Args...)int()である、すなわち、 "intを返す()の機能"、intあります。

is_functionがtrueを返すものは、値渡しの関数パラメータの型にはなりません。何をしたいのかは分かりません。

私はFuncは、そのためのArgs...

使用式SFINAEに適用することができ 機能(好ましくは関数ポインタ)であるとき、呼び出し可能のみにデリゲートを取得しようとしていました。

template <typename Func, typename... Args> 
auto delegate(Func f, Args... args) -> decltype(f(args...), void()); 

あなたが実際に何をしたいのかに応じて、std::movefargsにしたいことがあります。

+0

小さなコメント - 私はOPがデリゲートから関数の戻り値を返すことを望んでいると思います。だからおそらく 'decltype(f(args ...)); '(もちろん、私のところは純粋な推測です)。 – SergeyA

+0

私は実際に 'delegate'が' void'を返すようにしたいと思います。上記は素晴らしいですが、感謝します。 :)好奇心から、それはなぜ 'void()'ですか? – oconnor0

+0

単に 'decltype'が型を分解するためにオブジェクトを必要とするからです。 'void()'はvoid型のオブジェクトとして機能します。しかし、好奇心のために、なぜsfinaeが欲しいのですか?下の私の答えに示されているような単純な関数の何が間違っていますか? – SergeyA

3

あなたが書いたコードは、常にtrueになります。あなたがすべてでenable_ifを必要としないようではない、それは確からしいけどおそらくstd::is_function<Func>...

を意味し、私は間違っているとenable_ifがキーである場合は、しかし、単純な

template <class R, class... ARGS> 
R delegate2(R (*fun)(ARGS...), ARGS...); 

とのより良いいただきたいですこのコメントに基づいて

#include <type_traits> 

template <typename Func, typename... Args> 
typename std::enable_if<std::is_function<std::remove_pointer_t<Func>>::value>::type 
    delegate(Func, Args...); 

void check(int); 

int main(void) { 
    delegate(check, 10); // << good line compiles 
    delegate(10); // << this bad line does not 

    return 0; 
} 
+0

@ T.C。、私の更新された答えを見てください - それは適切なチェックコールで動作します。 – SergeyA

+0

@ T.C。、私はずっと前になぜ尋ねるのをやめました。とにかく、コードをより良いものに更新しました。 – SergeyA

+0

この最初の試みは、 'delegate2'のようなものでした。残念なことに、型が正確に一致する必要があります。つまり、 'fun'が' long'をとる場合、 'int'(リテラルなど)は渡せませんが、明示的にキャストする必要があります。コンバージョンを行うか、そうでなければ型の一致を助けるための代理コールを探していたいと思っていました。 – oconnor0

2

:あなたのケースの成功に、ここにあなたがこれを行うことができる方法である

が間違った型特性を使用している Args...

に適用できる関数(好ましくは関数ポインタ)であるとき

は、私は、デリゲートが唯一の呼び出し可能であることを取得しようとしていました。 FuncArgs...で呼び出し可能かどうかをチェックするには、これらの引数を使用して実際にFuncというインスタンスを呼び出す式を作成する必要があります。そのため、std::result_of_tは(C++ 14で、それは友好的SFINAEなります)があります:

template <typename Func, typename... Args, 
    class R = std::result_of_t<Func(Args...)>> 
R delegate(Func, Args...); 

あるいは、C++ 11には、ちょうどdecltypedeclvalとのことを書き出す:

template <typename Func, typename... Args, 
    class R = std::declval<Func>()(std::declval<Args>()...)> 
R delegate(Func, Args...); 
+0

'result_of'はあなたが望み、かつ' INVOKE'の完全な可能性を使用しない限り、間違ったことです。 –

関連する問題