Pregunta

Tengo algunos problemas para entender la necesidad de std::result_of en C ++ 0x. Si he entendido bien, result_of se utiliza para obtener el tipo resultante de invocar un objeto función con ciertos tipos de parámetros. Por ejemplo:

template <typename F, typename Arg>
typename std::result_of<F(Arg)>::type
invoke(F f, Arg a)
{
    return f(a);
}

Yo realmente no ver la diferencia con el siguiente código:

template <typename F, typename Arg>
auto invoke(F f, Arg a) -> decltype(f(a)) //uses the f parameter
{
    return f(a);
}

o

template <typename F, typename Arg>
auto invoke(F f, Arg a) -> decltype(F()(a)); //"constructs" an F
{
    return f(a);
}

El único problema que veo con estas dos soluciones es que necesitamos, ya sea:

  • tiene una instancia de la funtor para utilizarlo en la expresión pasó a decltype.
  • sabe un constructor definido para el funtor.

Estoy en lo cierto al pensar que la única diferencia entre decltype y result_of es que el primero necesita una expresión mientras que el segundo no lo hace?

¿Fue útil?

Solución

result_of WAS introducido en Boost , y luego incluido en TR1 , y finalmente en C 0x ++. Por lo tanto result_of tiene una ventaja que es compatible hacia atrás (con una biblioteca adecuada).

decltype es una cosa totalmente nueva en C ++ 0x, no restringe sólo para el tipo de retorno de una función, y es una característica del lenguaje.


De todos modos, en gcc 4.5, result_of se implementa en términos de decltype:

  template<typename _Signature>
    class result_of;

  template<typename _Functor, typename... _ArgTypes>
    struct result_of<_Functor(_ArgTypes...)>
    {
      typedef
        decltype( std::declval<_Functor>()(std::declval<_ArgTypes>()...) )
        type;
    };

Otros consejos

Si necesita el tipo de algo que no es algo así como una llamada a la función, std::result_of simplemente no se aplica. decltype() le puede dar el tipo de cualquier expresión.

Si nos limitamos sólo a los diferentes maneras de determinar el tipo de retorno de una llamada de función (entre std::result_of_t<F(Args...)> y decltype(std::declval<F>()(std::declval<Args>()...)), entonces hay una diferencia.

std::result_of<F(Args...) se define como:

  

Si la expresión   INVOKE (declval<Fn>(), declval<ArgTypes>()...) es así   formado cuando son tratados como una   operando sin evaluar (cláusula 5), ??el   typedef tipo de miembro designará a las   tipo decltype(INVOKE (declval<Fn>(), declval<ArgTypes>()...));   de lo contrario, no habrá ningún miembro   tipo.

La diferencia entre result_of<F(Args..)>::type y decltype(std::declval<F>()(std::declval<Args>()...) tiene que ver con que INVOKE. Usando declval / decltype directamente, además de ser un poco más largo que escribir, sólo es válida si F es directamente exigible (un tipo de objeto de función o una función o un puntero de función). result_of, además, apoya punteros a los miembros funciones y punteros a los datos de miembro.

En un principio, el uso de declval / decltype garantiza una expresión SFINAE de usar, mientras que std::result_of le podría dar un error de hardware en lugar de un fallo de la deducción. Eso se ha corregido en C ++ 14: std::result_of ahora se requiere que sea SFINAE local (gracias a este documento ).

Así que en un conformando C ++ 14 compilador, std::result_of_t<F(Args...)> es estrictamente superior. Es más claro, más corto, y correcta soportes más Fs .


menos, claro está, que se está usando en un contexto en el que no desea permitir que los punteros a los miembros, por lo std::result_of_t tendría éxito en un caso en el que es posible que desee que falle.

Con excepciones. A pesar de que es compatible con punteros a los miembros, result_of no funcionará si intenta crear una instancia de un inválido tipo-id . Estos incluyen una función que devuelve una función o tomar tipos abstractos por valor. Ex.:

template <class F, class R = result_of_t<F()>>
R call(F& f) { return f(); }

int answer() { return 42; }

call(answer); // nope

El uso correcto hubiera sido result_of_t<F&()>, pero eso es un detalle que no tiene que recordar con decltype.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top