3

関数/ファンクターの戻り値の型を知らずに (つまり、テンプレートとして) 使用する必要があります。

問題なく2番目の関数に渡すことができましたが:

template <typename T>
void DoSomething(T value);

...

DoSomething(FunctionWhoseReturnedTypeIsUnknown(...));

戻り値をインラインで使用したい (2 番目の関数を呼び出す必要はありません):

WhatGoesHere? x=FunctionWhoseReturnedTypeIsUnknown(...);

2 つの方法は概念的には同じように見えますが (ジェネリック プログラミングに関して)、後者は C++ で実現できますか?

4

5 に答える 5

5

auto キーワードによって本当に簡単になるまでは、関数オブジェクトが result_type を含む特定の typedef を提供するという規則に頼ることができます。単純な関数を関数オブジェクトにラップするだけです。標準の「機能的」ヘッダーは、いくつかの (2 つのメンバー関数ラッパーに加えて、pointer_to_unary_function/pointer_to_binary_function) を提供します。これらが不十分な場合、boost ライブラリはより強力なラッパーを提供します。

#include <iostream>
#include <boost/function.hpp>
#include <boost/bind.hpp>

int answer()
{
    return 42;
}

template <class T>
T unknown()
{
    return T();
}

template <class Function>
void foobar(Function unknown)
{
    typename Function::result_type x = unknown();
    std::cout << x << '\n';
}

int main()
{
    foobar(boost::function<int()>(answer));
    foobar(boost::bind(unknown<int>));
}

以下は、pointer_to_zeronary_function を追加する方法の例です。(作成に役立つヘルパー関数、ptr_fun は、標準の名前空間とオーバーロードに追加される可能性があると思います(?)

template <class T>
class pointer_to_zeronary_function
{
    typedef T(*zeronary_func)();
    zeronary_func func;
public:
    typedef T result_type;
    pointer_to_zeronary_function(zeronary_func f): func(f) {}
    T operator()() const
    {
        return func();
    }
};

template <class T>
pointer_to_zeronary_function<T> ptr_fun(T(*f)())
{
    return pointer_to_zeronary_function<T>(f);
}

...
//usage:
foobar(ptr_fun(answer));
于 2009-08-15T16:47:54.337 に答える
4

まだ。autoC++0X では、 asを使用できますWhatGoesHere。一部のコンパイラ (gcc 4.4 など) では、既に実験的なサポートが行われています。

于 2009-08-15T15:54:10.047 に答える
2

特定のユース ケースによって異なりますが、boost::anyを使用できる場合もあります。

#include <iostream>
#include <boost/any.hpp>

namespace {
  template <class T>
  T return_arg(T t) {
    return t;
  }
}

int main() {
  try {  
    boost::any i = return_arg(1);
    boost::any s = return_arg("a string");
    std::cout << boost::any_cast<int>(i) << " "
          << boost::any_cast<const char*>(s)
          << std::endl;
  }
  catch(const boost::bad_any_cast &) {
      return 1;
  }
}
于 2009-08-15T16:38:12.937 に答える
1

C++0x では、キーワード auto を使用して、推論された変数型の概念が導入されています。

auto x = SomeFunction();

結果は、C# の var キーワードと同じです。つまり、型が式の戻り値の型である厳密に型指定された変数です。

C++0x がない場合、テンプレートの外部でこれを実現する良い方法はありません。方法があれば、C++0x はこの機能を必要としません。

于 2009-08-15T15:53:04.837 に答える
1

これは本当に遅いですが、これを行う方法を理解しようとしていて、この質問に遭遇しました。私が使用している環境では C++11 (別名 C++0x) または Boost を使用できませんが、どちらも素晴らしいものです。後世の。

UncleBens がほのめかしたように、STL の機能ヘッダーには、C++ 11 または Boost を使用していない場合に役立つ機能がいくつかあります: http://www.cplusplus.com/reference/std/functional/

この問題は、2 番目のテンプレート関数を呼び出したくないということよりも、もう少し一般的なものです。たとえば、ファンクタの戻り値の型のベクトルを構築したい場合があります。この場合、2 番目のテンプレート関数の呼び出しは機能しない可能性があります。

関数のオーバーロード (関数ポインターとファンクターの両方を操作するため) と stl を使用することで、これを機能させることができます。変数を明示的に宣言した後、引数が 1 つのファンクター/関数の引数の結果を出力する例を次に示します。

#include <iostream>
#include <functional>

using namespace std;


// Simple function [pointer] that adds one to its argument
int addOne(int n)
{
    return n + 1;
}

// Simple functor that multiplies its argument by two
class timesTwo
{
    public:
    int operator()(int n) const { return n * 2; }
};


// Simple higher-order function: takes a functor f and calls f on n, returning the result
// This is your template function in which you want to know the return type of f
template <typename Functor>
void printResultImpl(Functor f, typename Functor::argument_type n)
{
    typename Functor::result_type r = f(n);
    cout << r << endl;
}


// Wrapper function for function pointer
template <typename Arg, typename Result>
void printResult(Result (*f)(Arg), Arg n)
{
    printResultImpl(ptr_fun(f), n);
}

// Wrapper function for functor (function object)
template <typename Functor, typename Arg>
void printResult(Functor f, Arg n)
{
    printResultImpl(bind1st(mem_fun(&Functor::operator()), &f), n);
}


// Prints out 8 then 14
int main()
{
    printResult(addOne, 7);
    printResult(timesTwo(), 7);
}

このメソッドにはいくつかの制限があります: 1. ファンクターの結果の型を関数に返すことはできません (ラッパー関数は結果の型を認識しないため) 2. stl の unary_function または binary_function に依存します。UncleBens が示したように、他の型に拡張することは可能です。単純に次の宣言のパターンに従ってください: http://www.cplusplus.com/reference/std/functional/

しかし、それは私が必要としていたものにはうまくいきました。多分それは他の誰かのために働くでしょう。

于 2011-10-02T00:56:26.617 に答える