4

誤解を招くような質問のタイトルを選択したため、この質問は完全な重複として閉じられました。間違いではありませんでしたが、この質問などでよく議論される問題を示唆していました。コンテンツは、Stackoverflow で取り上げられたことのないより具体的なトピックに関するものであるため、質問を再開していただきたいと思います。これは今起こったので、ここに質問があります。

パラメータとして 3 つの整数値を期待する関数を指定しlength(int x, int y, int z);ました。この関数を変更することはできません。たとえば、構造体またはタプルを単一のパラメーターとして受け入れるなどです。

上記の関数の単一の引数として使用できる別の関数を C++ で記述する方法はありlength(arguments());ますか?

とにかく、その関数の戻り値の型は であるarguments();必要があるようint, int, intです。しかし、私の知る限り、このような関数を C++ で定義して使用することはできません。によってリスト、タプル、構造体、またはクラスを返すことができることを知っていarguments()ます。一部の人々は私がこれについて尋ねたと思ったので、質問は閉じられました. しかし難しいのは、タプルや構造体などを 3 つの整数パラメータとして渡すことです。

これは可能ですか?そうであれば、C++でどのように可能ですか? C++11 を使用するソリューションは問題ありません。

4

6 に答える 6

8

あなたが望むことを直接行う方法はないと思いますが、コードのいくつかの場所で使用する C++11 の手法を次に示します。基本的な考え方は、私が呼び出したテンプレート関数を使用してcall_on_tuple、関数の引数fとさらに引数のタプルを取り、タプルを展開して、展開された引数のリストで関数を呼び出すことです。

template <typename Fun, typename... Args, unsigned... Is>
typename std::result_of<Fun(Args...)>::type
call_on_tuple(Fun&& f, std::tuple<Args...>&& tup, indices<Is...>)
{ return f(std::get<Is>(tup)...); }

したがって、アイデアは、呼び出す代わりに

length(arguments());

あなたは電話するでしょう

call_on_tuple(length,arguments());

これは、が変更されていることを前提としてarguments()いるため、 a が返されますstd::tuple<int,int,int>(これは基本的に、引用した質問からのアイデアです)。

ここで難しいのは、Is...引数 pack を取得する方法です。これは0,1,2,...、タプルの要素に番号を付けるために使用される整数のパックです。

0,1,2常に 3 つの引数を使用することが確実な場合は、文字通り使用できますが、任意の n 項関数でこれを機能させることが目的である場合は、他の投稿で説明されている別のトリックが必要です。この投稿への回答。

引数の数を整数sizeof...(Args)リスト0,1,...,sizeof...(Args)に変換するのはトリックです:

このトリックと の実装をcall_on_tuple名前空間に入れdetailます。

namespace detail {

  template <unsigned... Is>
  struct indices
  { };

  template <unsigned N, unsigned... Is>
  struct index_maker : index_maker<N-1,N-1,Is...>
  { };

  template <unsigned... Is>
  struct index_maker<0,Is...>
  { typedef indices<Is...> type; };


  template <typename Fun, typename... Args, unsigned... Is>
  typename std::enable_if<!std::is_void<typename std::result_of<Fun(Args...)>::type>::value,
              typename std::result_of<Fun(Args...)>::type>::type
  call_on_tuple(Fun&& f, std::tuple<Args...>&& tup, indices<Is...>)
  { return f(std::get<Is>(tup)...); }
}

現在、実際の関数call_on_tupleは次のようにグローバル名前空間で定義されています。

template <typename Fun, typename... Args>
typename std::enable_if<!std::is_void<typename std::result_of<Fun(Args...)>::type>::value,
            typename std::result_of<Fun(Args...)>::type>::type
call_on_tuple(Fun&& f, std::tuple<Args...>&& tup)
{
  using std::tuple;
  using std::forward;
  using detail::index_maker;

  return detail::call_on_tuple
    (forward<Fun>(f),forward<tuple<Args...>>(tup),typename index_maker<sizeof...(Args)>::type());
}

基本的にdetail::index_maker、増加する整数のリストを生成するために呼び出し、それを呼び出しますdetail::call_on_tuple

その結果、次のことができます。

int length(int x, int y, int z)
{ return x + y + z; }

std::tuple<int,int,int> arguments()
{ return std::tuple<int,int,int> { 1 , 2 , 3 }; }

int main()
{
  std::cout << call_on_tuple(length,arguments()) << std::endl;
  return 0;
}

これは、必要なものに十分近いことを願っています。

ノート。また、これが実際に値を返すenable_if関数でのみ使用されるようにするために、 も追加しました。fを返す関数の別の実装を簡単に作成できますvoid

途中で質問を閉じてしまい、重ねて申し訳ありません。

PS。これをテストするには、次の include ステートメントを追加する必要があります。

#include <tuple>
#include <type_traits>
#include <iostream>
于 2012-12-30T10:28:58.297 に答える
4

C++ では、別の関数の 3 つの個別の入力引数として使用できる 3 つの戻り値をネイティブに提供することはできません。

しかし、複数の値を返す「トリック」があります。これらのどれもあなたの質問に完璧な解決策を提供しませんが、length()変更せずに単一の引数として使用することはできないためlength()です。

structtupleまたはのようなコンテナ オブジェクトを使用します。class

typedef struct { int a,b,c; } myContainer;

myContainer arguments(int x, int y, int z) {
  myContainer result;
  result.a = 1;
  // etc
  return result;
}

myContainer c = arguments(x, y, z);
length(c.a, c.b, c.c);

トリックは、length()関数をオーバーロードすることです。そのため、単一の引数で使用できるように見えます。

void length(myContainer c) {
  length(c.a, c.b, c.c);
}

length(arguments());

もちろんinline、 、マクロなどを使用して、さらに最適化することもできます。

私はそれがまだあなたが望むものではないことを知っていますが、これが最も近いアプローチだと思います.

于 2012-12-30T09:26:29.220 に答える
1

ほとんどのプログラミング言語は、何らかの形式のアダプター関数を介してこれを行います。これは、呼び出す関数 (ここではlength) とそれを呼び出す引数を引数として取る関数です。おそらく、テンプレートを使用して C++ で同様のものを構築できます。functionalインスピレーションを得るためにヘッダーを見てください。

探しているものをネイティブに提供する言語は Perl です。あなたは書ける:

sub arguments {
    return 1, 2, 3;
}
sub length {
    my ($p1, $p2, $p3) = @_;
    # … Work with $p1, $p2 and $p3
}
length(arguments());
于 2012-12-30T09:42:02.530 に答える
1

または同様のものを宣言する必要がありますstruct { int a, b, c; }(クラスも機能します)-Pythonまたはphpなどをプログラミングしていると思います。

于 2012-12-30T09:22:50.340 に答える
-1

引数を参照渡しして、構造体を返すか返すことなく引数を変更できるようにします。関数から返せる値は 1 つだけです。

于 2012-12-30T09:24:29.493 に答える
-2

返すことができる値は1つだけです。ただし、複数の値を返したい場合は、配列を使用するか、オブジェクトまたは構造を定義できます

    int* arguments() {
        int x[1,4,6] 
        return x;
    };

    void length(int i[]);

    length(arguments());
于 2012-12-30T09:36:22.377 に答える