1

ある種のコンパイラを作成しようとしているので、かなりエキゾチックな問題があります...ラムダ式を次のようなテンプレート関数に渡したいです:

    template<class T>
delegate<T>* bind(std::function<T> func)
{
    return nullptr;
}

今電話できるように

bind([&](int a) { // do something });

...通常、std :: functionはラムダをキャプチャできるため、これは問題にはなりません。しかし、ここでの問題は、「T」が正確に何であるかについての情報を私が知らないか、提供したくないということです(仮定しましょう)。std :: function<>..に挿入できる任意の関数シグネチャにすることができます。

また、この「推測された」署名を、返したい「デリゲート」クラスに戻す必要があり、そのデリゲートクラスはクラスへのポインタである必要があります...

今のところ私はこれを思いついた:

template<class T>
struct delegate : public std::function<T>
{
    delegate(const std::function<T>& func) : std::function<T>(func) { }
    delegate(const delegate<T>& func) { }
};

template<class T>
delegate<T>* bind(std::function<T>&& func)
{
    return new delegate<T>(std::forward<std::function<T>>(func));
}

しかし、上記の「bind」の呼び出しの例は、「failedtemplateargumentdeduction」で失敗します。「bind」を呼び出すときに「T」パラメーターを明示的に指定せずにこれを機能させるにはどうすればよいですか(少なくとも機能します)。

理論的には、私のコンパイラにはこの問題を回避するためのすべての情報があるため、「T」のインスタンスを挿入するだけで済みますが、これにより、生成されたコードが不必要に複雑になります。

ところで、私は最新のClangコンパイラを使用しています。


最終的な解決策は次のとおりです。

    template<typename T> struct get_signature;
template<typename Mem, typename Ret, typename... Args> struct get_signature<Ret(Mem::*)(Args...) const> {
    typedef Ret type(Args...);
};

template<class T> 
delegate<typename get_signature<decltype(&T::operator())>::type>* bind(T func)
{
    return nullptr;
}

必要に応じて「const」修飾子を調整する必要がある場合があることに注意してください。

4

1 に答える 1

2

まず、右辺値参照を完全に台無しにしました。転送はまったく機能しません。

第二に、それが不可能な場合もあります。一部の関数オブジェクトoperator()では、メンバー関数ポインターを取得してその署名を検査することにより、署名を推測できます。しかし、他の人にとっては、それらは過負荷になり、機能しません。

template<typename T> struct get_signature;
template<typename Mem, typename Ret, typename... Args> 
struct get_signature<Ret(Mem::*)(Args...)> {
    typedef Ret(Args...) type;
};

template<class T> 
delegate<typename get_signature<&T::operator()>::type>* bind(T func)
{
    return nullptr;
}

第三に、std::bind

于 2012-12-01T20:32:52.933 に答える