2015-10-03 7 views
6

呼び出し可能の概念はhttp://en.cppreference.com/w/cpp/concept/Callableで定義されています。C++ 11では、任意の呼び出し可能オブジェクトを呼び出す方法は?

*私はタイプTの1つの引数を持つ F呼び出し可能オブジェクトを持っていると仮定し、タイプ無効を返します。 fは、任意の呼び出し可能な型(関数オブジェクト、メンバ関数へのポインタ、データメンバへのポインタなど)です。 fを呼び出すにはどうすればよいですか?

fはメンバー関数またはデータメンバーへのポインタであるため、単にf(x)を呼び出すだけで失敗します。電話する簡単な方法はありますかf?可能な解決策の1つはstd :: bind(f、x)()ですが、fにもっと引数があると、この解決法はより複雑になります。

+0

からの技術を使用して、ユースケースを持っていましたか? –

答えて

6

これはまさにstd::invokeの機能ですが、C++ 17まで標準ではありません。独自のバージョンを作成することはできますが、完全に一般的な場合はかなり複雑になる可能性があります。

template <class F, class... Args> 
inline auto INVOKE(F&& f, Args&&... args) -> 
    decltype(std::forward<F>(f)(std::forward<Args>(args)...)) { 
     return std::forward<F>(f)(std::forward<Args>(args)...); 
} 

template <class Base, class T, class Derived> 
inline auto INVOKE(T Base::*pmd, Derived&& ref) -> 
    decltype(std::forward<Derived>(ref).*pmd) { 
     return std::forward<Derived>(ref).*pmd; 
} 
+0

gcc 5.2で実装されていますか? – user3547691

+0

私はhttp://en.cppreference.com/w/cpp/utility/functional/invokeで提供されている実装をコピーすることができます。ありがとう。 – user3547691

+0

記録のために、明らかにMSVC2015は完全に実装されています。 – Adrian17

3

よりもむしろINVOKEを実装library features that uses itのいずれかを使用し、自分自身:ここ

は2例(cppreference.comから取られたコード)のための基本的な考え方です。特にstd::reference_wrapperが機能します。したがって、あなたはstd::ref(f)(args...)std::invoke(f, args...)の効果を持つことができます。

template<typename F, typename... Args> 
auto invoke(F f, Args&&... args) 
    -> decltype(std::ref(f)(std::forward<Args>(args)...)) 
{ 
    return std::ref(f)(std::forward<Args>(args)...); 
} 

std::reference_wrapperが渡されたオブジェクトが右辺値ではないことを必要とするため、私は前方fしませんでした。 std::refの代わりにstd::bindを使用しても問題は解決されません。 C++ 17でstd::invoke(F{})Rvalueを印刷し、一方、

struct F 
{ 
    void operator()() && { 
     std::cout << "Rvalue\n"; 
    } 
    void operator()() const& { 
     std::cout << "Lvalue\n"; 
    } 
}; 

invoke(F{})Lvalueを印刷します。これが意味することは、このような関数オブジェクトのためということです。

は私がthis paper

関連する問題