hilfs-template zur überladungsauflösung



  • hi,

    wieso funktioniert dieser code nicht?

    #include <functional>
    #include <cmath>
    
    template<typename... T>
    struct pick
    {
    	template<typename R, typename... U>
    	static auto from(R(*ptr)(T..., U...))
    	{
    		return ptr;
    	}
    };
    
    int main()
    {
    	std::function<double(double)>{pick<double>::from(&std::exp)};
    }
    

    exakte compiler-meldung hier:
    https://ideone.com/fiKBRc


  • Mod

    Seit C++11 haben die Standard-math-Funktionen zusätzliche Überladungen (neben float,double,long double).

    For each set of overloaded functions within <cmath>, there shall be additional overloads sufficient to ensure:
    1. If any argument of arithmetic type corresponding to a double parameter has type long double, then
    all arguments of arithmetic type (3.9.1) corresponding to double parameters are effectively cast to
    long double.
    2. Otherwise, if any argument of arithmetic type corresponding to a double parameter has type double
    or an integer type, then all arguments of arithmetic type corresponding to double parameters are
    effectively cast to double.
    3. Otherwise, all arguments of arithmetic type corresponding to double parameters have type float.

    Der Standard sagt nicht, wie diese Funktionssignaturen exakt auszusehen haben, im Falle von GNUs stdlibc++ existiert eine Überladung der Form

    template <typename U>
    constexpr typename std::enable_if<std::is_integral<U>{}, double>::type exp(U);
    

    für diesen Zweck.
    Das ist Problematisch, weil in dem gegebenen Kontext der endgültige Funktionstyp ja erst noch deduziert werden muss, U wiederum kann aber nur deduziert werden, wenn der Typ bereits bekannt ist (und nicht bloss ein Teil davon). Das ist daher leider auch kein Fall von SFINAE.


  • Mod

    Es fehlt leider ein Feature, dass es uns erlaubt, auflösbare Entitäten zu forwarden. Vielleicht kann man dazu ein Paper draften, aber in der Zwischenzeit

    #define wrapCallable(X) [] (auto&&... args) {return X(std::forward<decltype(args)>(args)...);}
    

    Und dann einfach

    std::function<double(double)>{wrapCallable(std::exp)};
    

    (ungetestet)



  • ok, danke euch beiden. schade, dass das noch nicht möglich ist mit unserer version von c++.


Anmelden zum Antworten