3

我需要在不知道它是什么类型的情况下使用函数/仿函数的返回值(即作为模板)。

虽然我可以毫无问题地将它传递给第二个函数:

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

...

DoSomething(FunctionWhoseReturnedTypeIsUnknown(...));

我想内联使用返回值(无需调用第二个函数):

WhatGoesHere? x=FunctionWhoseReturnedTypeIsUnknown(...);

这两种方法在概念上似乎与我相同(generic-programming-wize),但后者可以在 C++ 中实现吗?

4

5 回答 5

5

在 auto 关键字使它变得微不足道之前,可以依赖函数对象提供某些 typedef 的约定,包括 result_type。只需将一个普通函数包装到一个函数对象中。标准的“功能”标头提供了一些(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

还没有。在 C++0X 中,您将能够使用autoas 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 所暗示的,如果您不使用 C++11 或 Boost,STL 中的功能标头具有一些有用的功能: http ://www.cplusplus.com/reference/std/functional/

这个问题比不想调用第二个模板函数更普遍。例如,一个人可能想要构建一个函子返回类型的向量,在这种情况下调用第二个模板函数可能不起作用。

通过使用一些函数重载(对函数指针和函子进行操作)和 stl's ,我们可以完成这项工作。这是一个示例,它在显式声明变量后打印出单参数仿函数/函数参数的结果:

#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 回答