8

この回答には、次のようなコードスニペットがあります。

template<class T, class F>
auto f(std::vector<T> v, F fun)
    -> decltype( bool( fun(v[0] ) ), void() )
{
  // ...
}

それは実際にコンパイルされて動作します(少なくともIdeoneでは)。

では、この場合、タイプはどのように推定されますか?

次の行は本当にc++11標準で許可されていますか?

decltype( bool( fun(v[0] ) ), void() )

ざっと見てみましたが、有効ではありません。この場合、ideoneは間違っていますか?


c ++ 11標準のすべての例は、すべてdecltypeで1つの型のみを取得するようなものです。

struct A {
  char g();
  template<class T> auto f(T t) -> decltype(t + g())
  { return t + g(); }
};

もう一つの例 :

void f3() {
  float x, &r = x;
  [=] {
  decltype(x) y1;
  decltype((x)) y2 = y1;
  decltype(r) r1 = y1;
  decltype((r)) r2 = y2;
};

と別の

const int&& foo();
int i;
struct A { double x; };
const A* a = new A();
decltype(foo()) x1 = i;
decltype(i) x2;
decltype(a->x) x3;
decltype((a->x)) x4 = x3;

それらはすべて、decltypeで1つのパラメーターのみを取得しました。トップコードが2つのパラメーター(コンマで区切られている)を受け取るのはなぜですか?


私は別の例を作成しました(コンパイルに失敗します):

#include <vector>
#include <iostream>

template<class T, class F>
auto f(std::vector<T> v, F fun) -> decltype(bool(fun(v[0])), void())
{
  // ...
  (void)v;(void)fun;

  return fun(v.size());
}

void ops(int)
{
}

int main(){
  std::vector<int> v;
  f(v, [](int){ return true; });
  f(v,ops);
}

行が削除されても、テンプレート関数f(v,ops);の戻り型は無効と評価されます。f

4

2 に答える 2

14

decltype( bool( fun(v[0] ) ), void() )カンマ演算子を使用します。

分解して、

bool( fun(v[0] ) ), void()

2つの式で構成されています。最初

bool( fun(v[0] ) )

1と評価されて破棄され、式全体に値が与えられます

void()

これはタイプの値2voidです。

decltype次に、式のタイプを生成します。これは、上記のようにですvoid

ここでコンマ演算子を使用する理由は、最初の部分式が有効な場合にのみ式全体が有効になるようにするためです。これは、最初の部分式が無効な場合に置換の考慮から除外するためにSFINAEで使用されているためです。

これは、decltype構文的には関数のように見えますが、実際には(のようにsizeof)単一の引数を取るように定義されている言語構造であるために機能します。コンマ演算子の引数を括弧で囲む方が明確な場合があります。

decltype( ( bool( fun(v[0] ) ), void() ) )

ノート

  1. は評価されていないコンテキストにあるため、式bool( fun(v[0] ) )実際には評価されません(、と同様)。ここで重要なのは、式全体が評価された場合に評価されるため、部分式が無効な場合は式全体が無効になるということですdecltypesizeof
  2. void()は実際には値ではありませが、コンマ演算子とのコンテキストでは値のように動作しますdecltype
于 2012-08-02T10:38:10.380 に答える
7

decltype実際に評価せずに、括弧の間の式のタイプを生成します(次の部分でそれを覚えておいてください)。

演算子は、左側の,引数/式を評価し、結果を破棄し、右側の引数を評価して、その結果を生成します。そのため、戻りタイプはになりvoidます。

部分的にはbool(fun(v[0]))、それはかなり簡単です。bool(f(...))を呼び出した結果から一時的にboolを作成しfます。の戻りタイプがにf変換できない場合bool、これによりエラーがトリガーされ、内部にあるためにSFINAEが発生しますdecltype(これは「式SFINAE」と呼ばれます)。

f(v[0]) will pass the return value of v[0] to f, which is of type T&. If f doesn't have a parameter that T& is convertible to, or takes more / less parameters, this will trigger an error, and again, will lead to SFINAE for the same reason as above.

(The same would happen if std::vector wouldn't support operator[].)

于 2012-08-02T10:42:20.497 に答える