Tupel Type/Instanz per Template-Funktion erzeugen/instanzieren? geht das?



  • Ich würde gerne wissen ob man den mit "====> FRAGE" markierten von Hand ausgeschriebenen Code auch mit Templates machen kann - ich kenne mich leider noch nicht so gut aus mit Variadic Templates, Expression Folding, etc.

    Es geht um die Adaption von Methoden-Schnittstellen auf eine Abstraktes Interface - in diesem kompilierbaren Beispiel sieht man das aber nicht wirklich - das Beispiel ist hoffentlich klein genug und trotzdem ausreichend um mein Problem zu verstehen

    Würde mich über Tips oder Lösungsansätze freue - und Nein! Es ist keine Hausaufgabe 🙂

    Online Kompilieren/Ausführen: https://onlinegdb.com/rJGBenZN4

    Update: mal einen Versuch eingebaut um Frage 2 zu beantworten - ich scheitere kläglich 😞

    // aktuelle VS2017 Version, oder GCC 8.2, C++14 oder C++17 waere moeglich
    
    #include <tuple>
    #include <vector>
    #include <cassert>
    
    template<typename Value>
    struct in_parameter_t
    {
        in_parameter_t(void* value) {}
    };
    
    template<typename Value>
    struct out_parameter_t
    {
        out_parameter_t(void* value) {}
    };
    
    template<typename Value>
    struct inout_parameter_t
    {
        inout_parameter_t(void* value) {}
    };
    
    template<typename ValueType>
    struct parameter_type_t {};
    
    template<>
    struct parameter_type_t<int>
    {
        using type = in_parameter_t<int>;
    };
    
    template<>
    struct parameter_type_t<int&>
    {
        using type = inout_parameter_t<int>;
    };
    
    using parameter_t = std::vector<void*>;
    
    /*
    // Versuch Frage 2 zu beantworten - aber ausser viele viele Varianten von Kompilefehler komme ich da nicht weiter
    
    namespace detail 
    {
      template <typename TupleType_TP, size_t... Indices_TPs>
      auto get_parameter(parameter_t& parameter, std::index_sequence<Indices_TPs...>)
      {
        //return TupleType_TP(parameter[Indices_TPs]...);
        return TupleType_TP({ nullptr, nullptr });
      }
    }
    
    template <typename... Types_TPs>
    auto get_parameter(parameter_t& parameter)
    {
      return detail::get_parameter<std::tuple<Types_TPs...>>(parameter, std::index_sequence_for<Types_TPs...>());
    }
    */
    
    int main()
    {
        //------
        // Kompilezeit-Parameter
        // Methoden-Parameter-Typen
        using native_parameter_types = std::tuple<int,int&>;
        //------
        // Laufzeit-Parameter
        int p0 = 0;
        int p1 = 0;
        parameter_t parameter{&p0, &p1}; // muss ein std::vector sein (std::array ist zu fix)
        // zur Laufzeit garantiert das zu jedem native_parameter_types[x] ein parameter[x] existiert
        assert(parameter.size() == std::tuple_size<native_parameter_types>::value);
        //------
        
        // hier kommen mein Fragen
    
        // aus dem nativen typ einen adapter typ erzeugen
        using parameter_types_t = std::tuple
                                  <
                                  parameter_type_t<std::tuple_element<0, native_parameter_types>::type>::type,
                                  parameter_type_t<std::tuple_element<1, native_parameter_types>::type>::type
                                  >;
        //====> FRAGE 1: geht das auch mit einer Template-Funktion?
        //so in der Art?
        //using parameter_types_t = get_parameter_types<native_parameter_types>::types;
    
        // die adapter mit dem parameter-pointer instanzieren
        auto p = parameter_types_t
                 (
                     parameter[0],
                     parameter[1]
                 );
        //====> FRAGE 2: geht das auch mit einer Template-Funktion?
        //so in der Art?
        //auto p = get_parameter<parameter_types_t>(parameter);
    
        return 0;
    }
    

  • Mod

    Setz dich doch mal mit variadic templates auseinander, und insbesondere index Listen. Dann werden die Loesungen fuer dein Problem recht offensichtlich erscheinen.



  • ein Beispiel im Internet gefunden das schon mal einen gute Orientierung gibt

    die Frage 3 kann ich damit schon beantworten

    namespace detail {
    
    template <typename TupleType_TP, size_t... Indices_TPs, typename Callable_TP>
    void ForEachTupleElementImpl(TupleType_TP&& t, std::index_sequence<Indices_TPs...>, Callable_TP f)
    {
    #if 0 // C++14 trick
      using SinkHole_TP = int[];
      (void)SinkHole_TP {
      0, // This makes the array at least 1 element (0 elem arrays are ill-formed)
      ((void)(f(std::get<Indices_TPs>(t))), 0)...
    };
    #else // in VS2017 und LLVM muss der C++17 Standard aktiviert werden sonst kompiliert das nicht
      // In C++17, this can be done with a fold expression (new language construct) instead:
      (f(std::get<Indices_TPs>(t)), ...);
    #endif
    }
    
    }
    
    template <typename... Types_TPs, typename Callable_TP>
    void ForEachTupleElement(std::tuple<Types_TPs...>& t, Callable_TP f)
    {
      detail::ForEachTupleElementImpl(t, std::index_sequence_for<Types_TPs...>(), f);
    }
    
    // damit kann ich schon mal die Template-Funktion aus Frage 3 realisieren
    // aus
    //    std::get<0>(p).load();
    //    std::get<1>(p).load();
    // wird 
    //    load_parameter(p);
    
    template<typename NativeTypesTuple_TP>
    void load_parameter(NativeTypesTuple_TP& adapter)
    {
      ForEachTupleElement(adapter, [](auto&& e) { e.load(); });
    }
    


  • Alle Fragen beantwortet - Danke für die Tips


Log in to reply