4

この質問は基本的に、私が与えたこの回答の余波です。標準の文言では、いくつかのケースが省略されているように見えることに気付きました。次のコードを検討してください。

#include <iostream>
#include <functional>

struct foo
{
  void f(int v) { std::cout << v << std::endl; }
};

struct bar : foo {};

int main()
{
  bar obj;
  std::bind(&foo::f, obj, 1)();
}

標準では、20.8.9.1.2 で、その効果とstd::bind、それが呼び出されたときに何が起こるかについて説明しています。20.8.2 に転送されます。関連する部分は次のとおりです。

20.8.2 要件 [func.require]

1 INVOKE(f, t1, t2, ..., tN)を次のように定義します。

(t1.*f)(t2, ..., tN)fクラスのメンバ関数へのポインタでありTt1Tのオブジェクト、型のオブジェクトへのT参照、または から派生した型のオブジェクトへの参照である場合T

((*t1).*f)(t2, ..., tN)fクラスのメンバ関数へのポインタでありTt1前の項目で説明した型のいずれでもない場合。

—およびt1.*fがクラスのメンバ データへのポインタであり、が型のオブジェクト、または型のオブジェクトへの参照、または から派生した型のオブジェクトへの参照である場合。N == 1fTt1TTT

— and(*t1).*fがクラスのメンバ データへのポインタであり、前の項目で説明した型のいずれでもない場合。N == 1fTt1

f(t1, t2, ..., tN)その他のすべての場合。

これを読むと、最初のリスト項目に 3 つのケースが許可されているようです。

  • t1型のオブジェクトですT
  • または型のオブジェクトへの参照T
  • またはから派生した型のオブジェクトへの参照T

しかし、私の例では、どちらでもありません。から派生した型Tですが、参照はありません。上記のケースは次のとおりではありません。

  • t1型のオブジェクトですT
  • またはから派生した型のオブジェクトT
  • または型のオブジェクトへの参照T
  • またはから派生した型のオブジェクトへの参照T

もちろん、同じことが 20.8.2 の 3 番目のリスト項目にも当てはまります。

質問 1: GCC と Clang の両方が私のコードを受け入れるので、これは標準に対する欠陥レポートなのか、それとも私の読み方が間違っているだけなのか疑問に思います。

質問 2:多重/仮想継承では、型が から派生したものであっても、T単純に呼び出すことができない場合があり(t1.*f)(...)ますよね? それも私が懸念すべきことですか、それとも標準は特定のコンテキストで「派生元」を明確に定義していますか?

4

1 に答える 1

3

C ++ 11標準のパラグラフ20.8.9.1.3は、次のように疑似関数std::bind()の観点から呼び出しの効果を定義しています。INVOKE()

戻り値g:弱い結果タイプ(20.8.2)の転送コールラッパー。の効果g(u1, u2, ..., uM)INVOKE (fd, std::forward<V1>(v1), std::forward<V2>(v2), ..., std::forward<VN>(vN), result_of<FD cv & (V1, V2, ..., VN)>::type)

toを呼び出すと、左辺値参照であれ右辺値参照であれ、std::forward<>常に参照型が返されることに注意してください。パラグラフ20.2.3/1-2によると、実際には:

template <class T> constexpr T&& forward(typename remove_reference<T>::type& t) noexcept;

template <class T> constexpr T&& forward(typename remove_reference<T>::type&& t) noexcept;

戻り値static_cast<T&&>(t)

したがって、INVOKE疑似関数(注意:bind()関数ではありません!)は、ここで参照を使用して呼び出されます。これは、引用した定義によってサポートされています。

標準自体は、INVOKE()から派生したタイプのオブジェクト(オブジェクトへの参照ではない)で疑似関数(これは単なる内部形式です)を決して使用しないと思いますT

ただし、これは、から派生したタイプのオブジェクト(オブジェクトへの参照ではない)std::bind()に関して定義が指定されている関数やその他の関数を呼び出すことができないことを意味するものではありません。INVOKE()T

于 2013-03-09T13:22:17.907 に答える