简体   繁体   English

在C ++中推断函数或函子的返回类型

[英]Inferring the return type of a function or functor in C++

I need to use a function's/functor's returned value without knowing what type it is (that is, as a template). 我需要使用函数/函数的返回值,而不知道它是什么类型(即作为模板)。

While I could pass it over to a second function without a problem: 虽然我可以将它传递给第二个函数而没有问题:

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

...

DoSomething(FunctionWhoseReturnedTypeIsUnknown(...));

I want to use the returned value inline (without the need to call a second function): 我想使用返回的内联值(无需调用第二个函数):

WhatGoesHere? x=FunctionWhoseReturnedTypeIsUnknown(...);

The two methods seem conceptually identical to me (generic-programming-wize), but can the latter be achived in C++? 这两种方法在概念上看起来与我相同(generic-programming-wize),但后者是否可以在C ++中实现?

Until the auto keyword makes it really trivial, one can rely on the convention that function objects provide certain typedef's, including result_type. 在auto关键字使其变得非常简单之前,可以依赖于函数对象提供某些typedef的约定,包括result_type。 One just needs to wrap a plain function into a function object. 只需将普通函数包装到函数对象中即可。 The standard "functional" header provides some (pointer_to_unary_function/pointer_to_binary_function in addition to a couple of member function wrappers). 标准的“functional”头文件提供了一些(除了几个成员函数包装器之外还有pointer_to_unary_function / pointer_to_binary_function)。 When these are not enough, boost library provides more powerful wrappers. 当这些还不够时,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>));
}

And below's an example, how you might add a pointer_to_zeronary_function. 以下是一个示例,您可以如何添加pointer_to_zeronary_function。 (I suppose the helper function that helps you create one, ptr_fun, might be added to the standard namespace as well as an overload(?) (我想帮助你创建一个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));

Not yet. 还没。 In C++0X you'll be able to use auto as WhatGoesHere . 在C ++ 0X中,您将能够将auto用作WhatGoesHere There is already experimental support for this in some compilers (gcc 4.4 for instance). 在一些编译器中已经有了实验性支持(例如gcc 4.4)。

It depends on your specific use case but sometimes boost::any can be used: 这取决于您的具体用例,但有时可以使用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;
  }
}

C++0x introduces the concept of an inferred variable type by using the keyword auto. C ++ 0x通过使用关键字auto引入了推断变量类型的概念。

auto x = SomeFunction();

The result is the same as C#'s var keyword: a strongly typed variable whose type is the return type of the expression. 结果与C#的var关键字相同:一个强类型变量,其类型是表达式的返回类型。

In the absence of C++0x there is no good way to achieve this outside of a template. 在没有C ++ 0x的情况下,没有好的方法可以在模板外实现这一点。 If there ways, C++0x would have no need for this feature. 如果有方法,C ++ 0x将不需要此功能。

This is really late, but I was trying to figure out how to do this and ran into this question. 这真的很晚了,但我试图弄清楚如何做到这一点并遇到了这个问题。 The environment I'm using can't use C++11 (aka C++0x) or Boost, although both of those are awesome, so I figured I'd post how I figured out to do this without either for the sake of posterity. 我正在使用的环境不能使用C ++ 11(又名C ++ 0x)或Boost,虽然这些都很棒,所以我想我会发布如何在没有为此的情况下做到这一点后人。

As UncleBens alluded to, the functional header in the STL has some useful features if you aren't using C++11 or Boost: http://www.cplusplus.com/reference/std/functional/ 正如UncleBens所提到的,如果你不使用C ++ 11或Boost,STL中的函数头有一些有用的功能: http//www.cplusplus.com/reference/std/functional/

This problem is a bit more general than just not wanting to call a second template function. 这个问题比不想调用第二个模板函数更普遍。 For example, one might want to build a vector of the return type of a functor, in which case calling a second template function might not work. 例如,可能想要构建一个仿函数的返回类型的向量,在这种情况下,调用第二个模板函数可能不起作用。

By using some function overloading (to operate on both function pointers and functors) and stl's , we can make this work. 通过使用一些函数重载(对函数指针和仿函数进行操作)和stl,我们可以使这个工作。 Here's an example that prints out the result of a one-argument functor/function argument after declaring the variable explicitly: 这是一个示例,在明确声明变量后打印出单参数仿函数/函数参数的结果:

#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);
}

There are a couple limitations to this method: 1. You can't have your function return the result type of the functor (since the wrapper function doesn't know the result type) 2. It relies upon unary_function or binary_function in the stl. 这个方法有一些限制:1。你不能让函数返回仿函数的结果类型(因为包装器函数不知道结果类型)2。它依赖于stl中的unary_function或binary_function。 As UncleBens demonstrated, it's possible to extend to other types - simply follow the pattern of the declarations in : http://www.cplusplus.com/reference/std/functional/ 正如UncleBens所展示的那样,它可以扩展到其他类型 - 只需遵循以下声明的模式: http ://www.cplusplus.com/reference/std/functional/

But it worked for what I needed; 但它适用于我需要的东西; maybe it'll work for someone else. 也许它会为别人工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM