web-dev-qa-db-ja.com

std :: Tuple get()メンバー関数

_boost::Tuple_には、次のように使用されるget()メンバー関数があります。

_Tuple<int, string, string> t(5, "foo", "bar");
cout << t.get<1>();  // outputs "foo"
_

C++ 0x _std::Tuple_にはこのメンバー関数がないため、代わりに非メンバー関数形式を使用する必要があります。

_std::get<1>(t);
_

私には醜く見えます。

_std::Tuple_がメンバー関数を持たない特別な理由はありますか?それとも私の実装(GCC 4.4)だけですか?

50
HighCommander4

C++ 0xドラフトから:

[注:getが非メンバー関数である理由は、この機能がメンバー関数として提供されている場合、型がテンプレートパラメーターに依存するコードでは、templateキーワードを使用する必要があるためです。 —エンドノート]

これは次のコードで説明できます。

template <typename T>
struct test
{
  T value;
  template <int ignored>
  T&  member_get ()
  {  return value;  }
};

template <int ignored, typename T>
T&  free_get (test <T>& x)
{  return x.value;  }

template <typename T>
void
bar ()
{
  test <T>  x;
  x.template member_get <0> ();  // template is required here
  free_get <0> (x);
};
62
doublep

既存の回答は素晴らしいものであり、確かに標準化委員会にとってこの目的のために不可欠でした。しかし、私が言及するのに十分重要であると思う別の問題があります。

無料の関数を使用すると、インターフェイスを変更できますなしクラスの定義を変更します。グローバルgetを特殊化するだけで、任意のタイプを「取得可能」にすることができます。メンバー関数では、クラスを直接変更する必要があります。

範囲ベースのforは、クラス型のメンバーbegin/endを検索しますが、ADLを介して非メンバーbegin/endも検索します。これらのAPIは、begin/end関数を持たないものでも、任意のコンテナーで使用できます。たとえば、LibXML2要素タイプに特化して、xmlElement*よりも範囲ベースのforを使用できます。

メンバー関数でなければならない場合は、それを行うことはできません。

C++では、フリー関数は、さまざまな種類のクラスで実行できる多くの操作の自然なインターフェースです。

30
Nicol Bolas

N3090/3092、§20.4.2.6/ 8:「注:getが非メンバー関数である理由は、この機能がメンバー関数として提供されている場合、型がテンプレートパラメーターに依存するコードでは、templateキーワードを使用する必要があるためです。 。—文末脚注

12
Jerry Coffin