sorry, unimplemented: mangling nontype_argument_pack



  • Hallöle,

    Sorry für den blöden Threadtitel, aber der Fehler ist so umfangreich, mir ist da nichts besseres eingefallen. Folgendes Szenario: Ich habe angefangen, Boost.Lambda nachzuprogrammieren, alle Operatoren sowie Platzhalter funktionieren bereits. Was mir Probleme bereitet, ist eine Art while Konstrukt.

    Hier ein Beispiel, wie das ganze aussehen soll:

    auto f = while_(_0)[--_0];
    

    Diese Lambda nimmt also das erste Argument und dekrementiert es, bis es 0 ist.

    Alle Ausdrücke werden vom CRTP Klassentemplate expression<DerivedType> abgeleitet. while_ ist eine Funktion, die einen solchen Ausdruck nimmt und eine while_expression<CondType> zurückgibt. Für while_expression ist der operator [] überladen, der eine while_body_expression<CondType, BodyType> zurückgibt.

    while_body_expression sieht wie folgt aus:

    template <typename Cond, typename Body>
    struct while_body_expression : expression<while_body_expression<Cond, Body>>
    {
    	while_body_expression(Cond cond, Body body)
    		: cond(cond), body(body)
    	{}
    
    	template <typename... Args>
    	void operator () (Args&&... args) const
    	{
    		while(cond(std::forward<Args>(args)...))
    			body(std::forward<Args>(args)...);
    	}
    
    private:
    	Cond cond;
    	Body body;
    };
    

    Wenn ich die oben gegebene Lambda mit dem folgenden Stück Code instanziere und verwende:

    auto f = while_(_0)[--_0];
    int i = 20;
    f(i);
    

    , sagt mir der Compiler:

    In file included from ../main.cpp:3:0:
    ../lambda/arithmetic_ops.hpp: In instantiation of 'decltype (-- declval<Expr>()((forward<Args>)(lambda::prefix_decrement_expression::operator()::args)...)) lambda::prefix_decrement_expression<Expr>::operator()(Args&& ...) const [with Args = {int&}; Expr = lambda::argument_placeholder_expression<0u>; decltype (-- declval<Expr>()((forward<Args>)(lambda::prefix_decrement_expression::operator()::args)...)) = int&]':
    ../lambda/while.hpp:21:5:   required from 'void lambda::while_body_expression<Cond, Body>::operator()(Args&& ...) const [with Args = {int&}; Cond = lambda::argument_placeholder_expression<0u>; Body = lambda::prefix_decrement_expression<lambda::argument_placeholder_expression<0u> >]'
    ../main.cpp:14:5:   required from here
    ../lambda/arithmetic_ops.hpp:22:2: sorry, unimplemented: mangling nontype_argument_pack
    

    Wobei er in main.cpp auf die Zeile des Aufrufs verweist und in arithmetic_ops.hpp auf die Definition des operator --, die über folgende Makroinstanzierung

    DEFINE_UNARY_EXPRESSION(prefix_decrement, --)
    

    wie hier zu sehen aussieht:

    #define DEFINE_UNARY_EXPRESSION_TYPE(name, op) \
    	template <typename Expr> \
    	struct name##_expression : expression<name##_expression<Expr>> \
    	{ \
    		name##_expression(Expr expr) \
    			: expr(expr) \
    		{} \
    	\
    		template <typename... Args> \
    		auto operator () (Args&&... args) const \
    			-> decltype(op std::declval<Expr>()(std::forward<Args>(args)...)) \
    		{ \
    			return op expr(std::forward<Args>(args)...); \
    		} \
    	\
    	private: \
    		Expr expr; \
    	};
    
    #define DEFINE_UNARY_EXPRESSION(name, op) \
    	DEFINE_UNARY_EXPRESSION_TYPE(name, op) \
    	\
    	template <typename Derived> \
    	name##_expression<Derived> expression<Derived>::operator op () const \
    	{ \
    		return name##_expression<Derived>(derived_this()); \
    	}
    

    Dieses Makro definiert einen Typ prefix_decrement_expression und implementiert den in der Basisklasse expression<> deklarierten operator --.

    Was mich wurmt, ist, dass die Operatoren alle ohne das while funktionieren. Erst wenn ich ein while in die Lambda einbaue kommen diese Fehler, völlig unabhängig davon, welche Operatoren ich nun in der Lambda verwende. Auch sehe ich nirgens ein "non-type argument pack".

    Ich hoffe diese Fehlerbeschreibung ist irgendwie verständlich, ansonsten bitte einfach nachfragen.

    Grüße,
    PI



  • Hat denn niemand eine Idee? 😞



  • sorry, unimplemented: mangling nontype_argument_pack ist normalerweise ein Hinweis darauf, dass der Compiler irgendetwas, dass unterstützt werden soll noch nicht kann.
    Mit Deinem Code ist vermutlich alles i.O., nur kann der Compiler das in diesem speziellen Kontext noch nicht.



  • Ich weiß schon, dass der Hinweis das suggeriert. Aber ich hab doch nur argument packs mit Typen.



  • 314159265358979 schrieb:

    Ich weiß schon, dass der Hinweis das suggeriert. Aber ich hab doch nur argument packs mit Typen.

    Ich bin mir nicht sicher, wo das hier: lambda::argument_placeholder_expression<0u>; Body = lambda::prefix_decrement_expression<lambda::argument_placeholder_expression<0u> entsteht, aber da wird irgendwie ein Ganzahl-Argument eingesetzt. Ich tippe mal darauf, dass das Problem irgendwie darin liegt.



  • Das ist der Placeholder, das Placeholder Template sieht so aus:

    template <unsigned N>
    struct argument_placeholder_expression : expression<argument_placeholder_expression<N>>
    {
    	template <typename Head, typename... Tail>
    	auto operator () (Head&&, Tail&&... tail) const
    		-> decltype(argument_placeholder_expression<N - 1>()(std::forward<Tail>(tail)...))
    	{
    		return argument_placeholder_expression<N - 1>()(std::forward<Tail>(tail)...);
    	}
    };
    
    template <>
    struct argument_placeholder_expression<0> : expression<argument_placeholder_expression<0>>
    {
    	template <typename Head, typename... Tail>
    	Head operator () (Head&& head, Tail const&...) const
    	{
    		return head;
    	}
    };
    
    argument_placeholder_expression<0> const _0;
    argument_placeholder_expression<1> const _1;
    argument_placeholder_expression<2> const _2;
    argument_placeholder_expression<3> const _3;
    argument_placeholder_expression<4> const _4;
    argument_placeholder_expression<5> const _5;
    argument_placeholder_expression<6> const _6;
    argument_placeholder_expression<7> const _7;
    argument_placeholder_expression<8> const _8;
    argument_placeholder_expression<9> const _9;
    


  • Ich habe jetzt mal versucht, das Placeholder-Template durch je einen eigenen Typen für jeden Placeholder zu ersetzen. Hat leider nichts geändert.



  • Ich habe mal nach nontype_argument_pack gesucht, und bin dabei auf folgende Seite gestoßen: Seite.
    Dort wird etwas weiter unten beschrieben, was sich hinter einem nontype_argument_pack verbirgt, und anscheinend sind das neben ordinalen Konstanten auch Funktionsargumente. Vielleicht hängt es irgendwie mit dem Forwarding zusammen.



  • Okay, das wäre möglich, aber ich kanns mir irgendwie nicht vorstellen, bzw verstehe es auch nicht. Denn das while ruft die Expressions auch nicht anders auf, als es die Operatoren und Placeholder tun, und ohne funktioniert es ja offensichtlich 😞



  • Schreib' doch vielleicht mal die Compilerbauer an. Vielleicht ist das ein Bug.



  • War wohl wirklich irgendwas unimplementiert, auch wenn ich nicht weiß, was. Hab nun nen GCC 4.8 und es läuft. 🤡


Anmelden zum Antworten