Kopie oder konstante Referenz?



  • Polynomteiler schrieb:

    Das wären extrem viele Spezialisierungen, das widerstrebt irgendwie dem Prinzip der Templates.

    Och, es geht.

    template <typename T> struct identity { typedef T type; };
    
    template <typename T, bool B> struct val_or_cref : identity<T> {};
    template <typename T> struct val_or_cref<T, false> : identity<T const&> {};
    
    template <typename T> struct per_value_candidate
    : std::integral_constant<bool, std::is_pod<T>::value && sizeof(T)<=sizeof(void*)> {};
    
    template <typename T,
              bool PerValue = per_value_candidate<T>::value>
    T calc(typename val_or_cref<T, PerValue>::type t)
    {
      std::cout <<
        (std::is_reference<typename val_or_cref<T, PerValue>::type>::value
         ? "per const-ref" : "per value") << '\n';
      return t;
    }
    
    int main()
    {
      calc<int>(4);
      calc<std::string>("x");
      calc<int*>(0);
    }
    

    Mich stört eher, dass T nicht mehr deduziert werden kann. Deshalb würde ich das niemals so machen und mich auf den Compiler verlassen.



  • Tachyon schrieb:

    Du könntest auch was mit enable_if und is_fundamental basteln.

    Edit: Ach, das hat der Sepp ja quasi schon geschrieben.

    Jetzt, wo du es erwähnst, fällt mir ein, dass ich mal ein Select<bool,typename,typename> geschrieben habe. 😃

    Daran hätte ich mal eher denken sollen, danke



  • Polynomteiler schrieb:

    Bringt es eigentlich wirklich so viel, Standardtypen und Iteratoren als Kopie anstatt als Referenz zu übergeben? Was daran effizienter sein soll, habe ich nie wirklich verstanden.

    Theoretisch bringt es sehr, sehr viel. Kannst dir ja mal den Unterschied überlegen zwischen einem Wert in einem Register und einem Zeiger auf den Wert. Praktisch wird's aber eh wegoptimiert.



  • cooky451 schrieb:

    Praktisch wird's aber eh wegoptimiert.

    Nur wenn die Funktion in der gleichen UE definiert wird. Das ist bei Templates zufällig der Fall.



  • Und wenn nicht könnte auch LTO greifen. Ansonsten haben Zeiger und Referenzen ohne Optimierung natürlich eine Indirektion mehr als eine Kopie, deren Auflösung Zeit kostet.



  • Ich werf mal einenspontanen Vorschlag in den Ring, mal gucken wer ihn zerreißt:

    template <typename T>
        T calc(T&& t); //C++11 "universal reference"
    


  • praktiker schrieb:

    Nur wenn die Funktion in der gleichen UE definiert wird. Das ist bei Templates zufällig der Fall.

    Ich nehme Compiler ohne Link-Time-Optimization eh nicht mehr ernst. 😉





  • Boost.CallTraits

    Und verwende bitte nicht den Begriff "konstante Referenz". Warum, erfährst du hier.


  • Mod

    cooky451 schrieb:

    Polynomteiler schrieb:

    Bringt es eigentlich wirklich so viel, Standardtypen und Iteratoren als Kopie anstatt als Referenz zu übergeben? Was daran effizienter sein soll, habe ich nie wirklich verstanden.

    Theoretisch bringt es sehr, sehr viel. Kannst dir ja mal den Unterschied überlegen zwischen einem Wert in einem Register und einem Zeiger auf den Wert.

    Das. Außerdem ist ein per Value übergebenes Argument garantiert aliasfrei.

    pumuckl schrieb:

    Ich werf mal einenspontanen Vorschlag in den Ring, mal gucken wer ihn zerreißt:

    template <typename T>
        T calc(T&& t); //C++11 "universal reference"
    

    Das ist immer noch eine Referenz.



  • camper schrieb:

    pumuckl schrieb:

    Ich werf mal einenspontanen Vorschlag in den Ring, mal gucken wer ihn zerreißt:

    template <typename T>
        T calc(T&& t); //C++11 "universal reference"
    

    Das ist immer noch eine Referenz.

    Nicht nur das, sie ist auch nicht mal const, man kann also das Objekt darüber verändern, das bringt's irgendwie so gar nicht?


Anmelden zum Antworten