2011-02-23 15 views
12

Siendo no declarado constexpr, std::forward descartará la consistencia para cualquier función a la que reenvía argumentos. ¿Por qué el std::forward no está declarado como constexpr, por lo que puede preservar la consistencia?¿Por qué std :: forward descarta la consistencia?

Ejemplo: (probado con g ++ instantánea-2011-02-19)

#include <utility> 

template <typename T> constexpr int f(T x) { return -13;} 
template <typename T> constexpr int g(T&& x) { return f(std::forward<T>(x));} 

int main() { 
    constexpr int j = f(3.5f); 
    // next line does not compile: 
    // error: ‘constexpr int g(T&&) [with T = float]’ is not a constexpr function 
    constexpr int j2 = g(3.5f); 
} 

Nota: técnicamente, sería fácil de hacer std::forward constexpr, por ejemplo, al igual que (nótese que en g std::forward tiene sido sustituido por fix::forward):

#include <utility> 

namespace fix { 
    /// constexpr variant of forward, adapted from <utility>: 
    template<typename Tp> 
    inline constexpr Tp&& 
    forward(typename std::remove_reference<Tp>::type& t) 
    { return static_cast<Tp&&>(t); } 

    template<typename Tp> 
    inline constexpr Tp&& 
    forward(typename std::remove_reference<Tp>::type&& t) 
    { 
    static_assert(!std::is_lvalue_reference<Tp>::value, "template argument" 
      " substituting Tp is an lvalue reference type"); 
    return static_cast<Tp&&>(t); 
    } 
} // namespace fix 

template <typename T> constexpr int f(T x) { return -13;} 
template <typename T> constexpr int g(T&& x) { return f(fix::forward<T>(x));} 

int main() { 
    constexpr int j = f(3.5f); 
    // now compiles fine: 
    constexpr int j2 = g(3.5f); 
} 

Mi pregunta es: ¿por qué no std::forward define como fix::forward?

Nota 2: Esta pregunta es algo relacionado con mi otra question about constexpr std::tuple como std::forward no ser constexpr es la razón técnica por std::tuple no se puede crear llamando a su cstr con rvalues, pero esta pregunta aquí, obviamente, es (mucho) más general.

+1

nota rápida, los identificadores que comienzan por '_ [A-Z]' están reservados para los implementadores del compilador. Su programa, como tal, está mal formado. –

+3

Y _T es especialmente desagradable si alguna vez te mudas a Windows, donde es una macro ... –

+1

@Matthieu M, @Bo Persson Gracias. Reemplacé todos los nombres _T por T, etc. para que otros puedan probar el código de forma más segura y fácil. – Lars

Respuesta

10

La respuesta general es que el Grupo de trabajo de bibliotecas del comité de C++ no ha realizado una búsqueda exhaustiva del borrador de trabajo en busca de oportunidades para utilizar las nuevas instalaciones centrales. Estas características se han utilizado donde las personas han tenido el tiempo y la inclinación para ver los posibles usos, pero no hay tiempo para una verificación exhaustiva.

Hay algunos documentos sobre usos adicionales de constexpr en las obras, como los del November 2010 mailing.

+0

Gracias. Conocía el documento relacionado [N3231] (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3231.html) ya, pero no menciona la sección 20.3.3 en std ::adelante. - Lo que proporcionas es más una "razón social". Estoy interesado en una "razón conceptual", es decir, ¿hay algo incorrecto en hacer std :: forward constexpr o estaría bien? – Lars

+4

No puedo ver ninguna razón por la que no a primera vista. –

+0

Con informes de problemas para hacer posible pasar y llamar a los punteros de función en funciones constexpr (y los tipos de objeto de función literal pueden ser construsos), tener std :: forward ser no constexpr parece desafortunado. –

Cuestiones relacionadas