<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Argumentzähler bei auto Parametern]]></title><description><![CDATA[<p>Hi,</p>
<p>ich habe eine Klasse, der man eine Funktion mitgeben kann. Je nachdem, ob die übergebene Funktion einen oder zwei Parameter entgegen nimmt, hat die Klasse eine per enable_if aktivierte entsprechende Methode, die die Funktion verwendet.</p>
<p>Minimalbeispiel:</p>
<pre><code>#include &lt;iostream&gt;

template &lt;typename T&gt;
struct get_arity : get_arity&lt;decltype(&amp;T::operator())&gt; {};
template &lt;typename R, typename... Args&gt;
struct get_arity&lt;R(*)(Args...)&gt; : std::integral_constant&lt;unsigned, sizeof...(Args)&gt; {};
template &lt;typename R, typename C, typename... Args&gt;
struct get_arity&lt;R(C::*)(Args...)&gt; : std::integral_constant&lt;unsigned, sizeof...(Args)&gt; {};
template &lt;typename R, typename C, typename... Args&gt;
struct get_arity&lt;R(C::*)(Args...) const&gt; : std::integral_constant&lt;unsigned, sizeof...(Args)&gt; {};

template&lt;typename T&gt;
void print(T fn)
{
	std::cout &lt;&lt; get_arity&lt;T&gt;::value &lt;&lt; &quot;\n&quot;;
}

int main() {
	print([](){});
	print([](int){});
	print([](int, int){});

	return 0;
}
</code></pre>
<p>Das funktioniert so und gibt 0,1,2 aus. Um den Typ der Parameter nicht angegeben zu müssen, wollte ich auto verwenden. Ein Lambda mit einem auto Parameter (z.B.:)</p>
<pre><code>print([](auto){});
</code></pre>
<p>erzeugt im GCC die Meldung</p>
<pre><code>prog.cpp: In instantiation of 'struct get_arity&lt;main()::&lt;lambda(auto:1)&gt; &gt;':
prog.cpp:16:12:   required from 'void print(T) [with T = main()::&lt;lambda(auto:1)&gt;]'
prog.cpp:21:18:   required from here
prog.cpp:5:8: error: decltype cannot resolve address of overloaded function
 struct get_arity : get_arity&lt;decltype(&amp;T::operator())&gt; {};
        ^
prog.cpp: In instantiation of 'void print(T) [with T = main()::&lt;lambda(auto:1)&gt;]':
prog.cpp:21:18:   required from here
prog.cpp:16:12: error: 'value' is not a member of 'get_arity&lt;main()::&lt;lambda(auto:1)&gt; &gt;'
  std::cout &lt;&lt; get_arity&lt;T&gt;::value &lt;&lt; &quot;\n&quot;;
            ^
</code></pre>
<p>und in VS2015 die etwas aussagekräftigere Meldung</p>
<pre><code>C3539	Ein Vorlagenargument darf keinen Typ aufweisen, der &quot;auto&quot; enthält
</code></pre>
<p>Kriegt man das auch irgendwie mit den auto Lambdas hin?</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/337272/argumentzähler-bei-auto-parametern</link><generator>RSS for Node</generator><lastBuildDate>Sat, 18 Apr 2026 08:25:07 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/337272.rss" rel="self" type="application/rss+xml"/><pubDate>Mon, 21 Mar 2016 00:00:36 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Argumentzähler bei auto Parametern on Mon, 21 Mar 2016 00:00:36 GMT]]></title><description><![CDATA[<p>Hi,</p>
<p>ich habe eine Klasse, der man eine Funktion mitgeben kann. Je nachdem, ob die übergebene Funktion einen oder zwei Parameter entgegen nimmt, hat die Klasse eine per enable_if aktivierte entsprechende Methode, die die Funktion verwendet.</p>
<p>Minimalbeispiel:</p>
<pre><code>#include &lt;iostream&gt;

template &lt;typename T&gt;
struct get_arity : get_arity&lt;decltype(&amp;T::operator())&gt; {};
template &lt;typename R, typename... Args&gt;
struct get_arity&lt;R(*)(Args...)&gt; : std::integral_constant&lt;unsigned, sizeof...(Args)&gt; {};
template &lt;typename R, typename C, typename... Args&gt;
struct get_arity&lt;R(C::*)(Args...)&gt; : std::integral_constant&lt;unsigned, sizeof...(Args)&gt; {};
template &lt;typename R, typename C, typename... Args&gt;
struct get_arity&lt;R(C::*)(Args...) const&gt; : std::integral_constant&lt;unsigned, sizeof...(Args)&gt; {};

template&lt;typename T&gt;
void print(T fn)
{
	std::cout &lt;&lt; get_arity&lt;T&gt;::value &lt;&lt; &quot;\n&quot;;
}

int main() {
	print([](){});
	print([](int){});
	print([](int, int){});

	return 0;
}
</code></pre>
<p>Das funktioniert so und gibt 0,1,2 aus. Um den Typ der Parameter nicht angegeben zu müssen, wollte ich auto verwenden. Ein Lambda mit einem auto Parameter (z.B.:)</p>
<pre><code>print([](auto){});
</code></pre>
<p>erzeugt im GCC die Meldung</p>
<pre><code>prog.cpp: In instantiation of 'struct get_arity&lt;main()::&lt;lambda(auto:1)&gt; &gt;':
prog.cpp:16:12:   required from 'void print(T) [with T = main()::&lt;lambda(auto:1)&gt;]'
prog.cpp:21:18:   required from here
prog.cpp:5:8: error: decltype cannot resolve address of overloaded function
 struct get_arity : get_arity&lt;decltype(&amp;T::operator())&gt; {};
        ^
prog.cpp: In instantiation of 'void print(T) [with T = main()::&lt;lambda(auto:1)&gt;]':
prog.cpp:21:18:   required from here
prog.cpp:16:12: error: 'value' is not a member of 'get_arity&lt;main()::&lt;lambda(auto:1)&gt; &gt;'
  std::cout &lt;&lt; get_arity&lt;T&gt;::value &lt;&lt; &quot;\n&quot;;
            ^
</code></pre>
<p>und in VS2015 die etwas aussagekräftigere Meldung</p>
<pre><code>C3539	Ein Vorlagenargument darf keinen Typ aufweisen, der &quot;auto&quot; enthält
</code></pre>
<p>Kriegt man das auch irgendwie mit den auto Lambdas hin?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2490970</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2490970</guid><dc:creator><![CDATA[KN4CK3R]]></dc:creator><pubDate>Mon, 21 Mar 2016 00:00:36 GMT</pubDate></item><item><title><![CDATA[Reply to Argumentzähler bei auto Parametern on Mon, 21 Mar 2016 10:32:24 GMT]]></title><description><![CDATA[<p>Hiho,</p>
<p>also ohne dir jetzt eine genaue ISO-Regel nennen zu können, die das erklärt: deine print-Funktion ist ein Template. Der Compiler soll hier also aus dem Argument den Typ ableiten. Das Argument selbst ist aber ein Lambda mit auto, wo auch eine Typherleitung notwendig ist über den Parametertyp (der ja wie grad geschrieben hergeleitet werden muss). Da beißt sicht die Katze in den Schwanz.</p>
<p>VG</p>
<p>Pellaeon</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2490996</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2490996</guid><dc:creator><![CDATA[Pellaeon]]></dc:creator><pubDate>Mon, 21 Mar 2016 10:32:24 GMT</pubDate></item><item><title><![CDATA[Reply to Argumentzähler bei auto Parametern on Mon, 21 Mar 2016 10:55:10 GMT]]></title><description><![CDATA[<p>Aber &quot;auto&quot; ist ja nur 1 Parameter. An der Stelle ist mir ja total egal, was auto für einen Typ hat, ich will nur die Anzahl der autos haben. Und falls du das missverstanden hast, auto lambdas sind bei der print Funktion kein Problem, erst wenn ich die Anzahl der Parameter wissen möchte wird auto zum Problem.</p>
<pre><code>template&lt;typename T&gt;
void print(T fn)
{
    fn(1, 2);
}

print([](auto&amp;&amp; x, auto&amp;&amp; y) { std::cout &lt;&lt; x &lt;&lt; y; });
</code></pre>
<p>Das funktioniert ganz normal. Hier nochmal ein Minimalbeispiel von dem was ich erreichen möchte:</p>
<pre><code>template&lt;typename T&gt;
struct Printer
{
	T fn;

	explicit Printer(T _fn)
		: fn(std::move(_fn))
	{
	}

	//das print, falls fn 1 Parameter nimmt
	void print()
	{
		fn(1);
	}

	//das print, falls fn 2 Parameter nimmt
	void print()
	{
		fn(1, 2);
	}
};

auto fn = [](auto&amp;&amp; x) { std::cout &lt;&lt; x; };
Printer&lt;decltype(fn)&gt;(fn).print();

auto fn2 = [](auto&amp;&amp; x, auto&amp;&amp; y) { std::cout &lt;&lt; x &lt;&lt; y; };
Printer&lt;decltype(fn2)&gt;(fn2).print();
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2490999</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2490999</guid><dc:creator><![CDATA[KN4CK3R]]></dc:creator><pubDate>Mon, 21 Mar 2016 10:55:10 GMT</pubDate></item><item><title><![CDATA[Reply to Argumentzähler bei auto Parametern on Mon, 21 Mar 2016 10:57:38 GMT]]></title><description><![CDATA[<p>Ist wahrscheinlich ein XY-Problem, daher solltest du eher beschreiben, was das ganze soll.</p>
<p>Das Problem besteht darin, dass Template Argumente erraten werden müssen, was natürlich nur in die Hose gehen kann, wenn das Lambda nur bestimmte Dinge annimmt (wovon auszugehen ist). Partial ordering ausnutzen ist unmöglich. Gut ist, dass es noch keine Concepts gibt, weswegen ein Parameter entweder alles nimmt oder einen gegebenen Typen hat.</p>
<p>Es gibt eine Annahme, die wir machen müssen, um die Arität halbwegs zuverlässig bestimmen zu können: Das Lambda hat einen trailing return type, der die Template Argumente nicht einschränkt (e.g. <code>void</code> ). So muss der Rumpf nicht instantiiert werden.</p>
<pre><code>#include &lt;type_traits&gt;
#include &lt;utility&gt;

template &lt;typename T&gt;
constexpr auto mem_op_arity = mem_op_arity&lt;decltype(&amp;T::operator())&gt;;

#define ARITY_REM_CTOR(...) __VA_ARGS__
#define ARITY_SPEC(cv, var)                                         \
template &lt;typename C, typename R, typename... Args&gt;           \
constexpr auto mem_op_arity&lt;R (C::*) (Args... ARITY_REM_CTOR var) cv&gt; = sizeof...(Args);

ARITY_SPEC(const, (,...))
ARITY_SPEC(const, ())
ARITY_SPEC(, (,...))
ARITY_SPEC(, ())

#undef ARITY_SPEC

namespace detail {
    struct arbitrary {template &lt;typename T&gt; operator T&amp;&amp;();};
    template &lt;std::size_t&gt;
	arbitrary ignore;

	template &lt;typename L, std::size_t... Is,
	          typename U = decltype(std::declval&lt;L&gt;()(ignore&lt;Is&gt;...))&gt;
	constexpr auto try_args(std::index_sequence&lt;Is...&gt;) {return sizeof...(Is);}

	template &lt;std::size_t I, typename L&gt;
	constexpr auto arity_temp(int)
	  -&gt; decltype(try_args&lt;L&gt;(std::make_index_sequence&lt;I&gt;{})) {
		return try_args&lt;L&gt;(std::make_index_sequence&lt;I&gt;{});}
	template &lt;std::size_t I, typename L&gt;
	constexpr std::enable_if_t&lt;(I == 32), std::size_t&gt; arity_temp(...) {
		return -1;}
	template &lt;std::size_t I, typename L&gt;
	constexpr std::enable_if_t&lt;(I &lt; 32), std::size_t&gt; arity_temp(...) {
		return arity_temp&lt;I+1, L&gt;(0);}

	template &lt;typename L, typename=decltype(&amp;L::operator())&gt;
	constexpr auto arity(int) {return mem_op_arity&lt;L&gt;;}
	template &lt;typename L&gt;
	constexpr auto arity(...) {return arity_temp&lt;0, L&gt;(0);}
}

template &lt;typename L&gt;
constexpr std::size_t arity(L&amp;&amp; l) {return detail::arity&lt;std::decay_t&lt;L&gt;&gt;(0);}

#include &lt;iostream&gt;

int main() {
	std::cout &lt;&lt; arity([] (auto a, int) -&gt; void {std::cout &lt;&lt; a.e;});
}
</code></pre>
<p><a href="http://coliru.stacked-crooked.com/a/7e81f7a0da010665" rel="nofollow">Die Ausgabe ist 2</a>.</p>
<p><a href="http://rextester.com/RHSTT42996" rel="nofollow">Geht auch auf VC++</a>, mit kleinen Änderungen (weil der Compiler eben Dreck ist).</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2491000</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2491000</guid><dc:creator><![CDATA[Columbo]]></dc:creator><pubDate>Mon, 21 Mar 2016 10:57:38 GMT</pubDate></item><item><title><![CDATA[Reply to Argumentzähler bei auto Parametern on Mon, 21 Mar 2016 11:59:58 GMT]]></title><description><![CDATA[<p>Ok, dein Code zählt auch auto Parameter. Lässt sich das jetzt noch so umbauen, dass es per enable_if das jeweilige print bei der Klasse in meinem zweiten Post aktiviert?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2491007</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2491007</guid><dc:creator><![CDATA[KN4CK3R]]></dc:creator><pubDate>Mon, 21 Mar 2016 11:59:58 GMT</pubDate></item><item><title><![CDATA[Reply to Argumentzähler bei auto Parametern on Mon, 21 Mar 2016 12:37:04 GMT]]></title><description><![CDATA[<p>KN4CK3R schrieb:</p>
<blockquote>
<p>Ok, dein Code zählt auch auto Parameter. Lässt sich das jetzt noch so umbauen, dass es per enable_if das jeweilige print bei der Klasse in meinem zweiten Post aktiviert?</p>
</blockquote>
<p><a href="http://coliru.stacked-crooked.com/a/002739ee0fa9dcf1" rel="nofollow">Überflüssig</a>:</p>
<pre><code>//das print, falls fn 1 Parameter nimmt
    template &lt;typename U&gt;
    auto print_(U&amp; fn) -&gt; decltype(fn(1))
    {
        return fn(1);
    }

    //das print, falls fn 2 Parameter nimmt
    template &lt;typename U&gt;
    auto print_(U&amp; fn) -&gt; decltype(fn(1, 2))
    {
        return fn(1, 2);
    }

    auto print() {return print_(fn);}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2491013</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2491013</guid><dc:creator><![CDATA[Columbo]]></dc:creator><pubDate>Mon, 21 Mar 2016 12:37:04 GMT</pubDate></item><item><title><![CDATA[Reply to Argumentzähler bei auto Parametern on Mon, 21 Mar 2016 13:03:36 GMT]]></title><description><![CDATA[<p>Hm, so einfach...</p>
<p>Jetzt noch ein letzter Punkt dazu. In der Klasse befindet sich folgendes Typedef:</p>
<pre><code>static typename TSource::value_type get_source();
static TFunction get_function();

typedef decltype(get_function()(get_source())) value_type;
//typedef decltype(get_function()(get_source(), 0)) value_type; ???
</code></pre>
<p>TFunction ist T aus meinem Printer Beispiel. TSource::value_type ist der Typ des ersten Parameters der Funktion. Der zweite optionale Parameter ist ein size_t.</p>
<p>value_type soll der Typ des Rückgabewerts der übergebenen Funktion sein. Wie muss ich das schreiben, wenn die Funktion 1 oder 2 Parameter hat.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2491015</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2491015</guid><dc:creator><![CDATA[KN4CK3R]]></dc:creator><pubDate>Mon, 21 Mar 2016 13:03:36 GMT</pubDate></item><item><title><![CDATA[Reply to Argumentzähler bei auto Parametern on Mon, 21 Mar 2016 14:18:56 GMT]]></title><description><![CDATA[<p>Wir könnten ein hübsches Makro schreiben:</p>
<pre><code>#include &lt;utility&gt;
#include &lt;tuple&gt;

template &lt;typename T, typename U&gt;
struct overload_t : T, U {
	using T::operator();
	using U::operator();
};
template &lt;typename T, typename... X&gt;
struct type_wrap {using type = decltype(std::declval&lt;T&gt;()(std::declval&lt;X&gt;()...));};
template &lt;typename T, typename U, typename... X&gt;
type_wrap&lt;overload_t&lt;T, U&gt;, X...&gt; overload(std::tuple&lt;X...&gt;, T&amp;&amp;, U&amp;&amp;) {return {};}

#define FIRST_(a, b) a
#define SECOND_(a, b) b
#define FIRST(x) FIRST_ x
#define SECOND(x) SECOND_ x
#define COUNT_(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, ...) _10
#define COUNT(...) COUNT_(__VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
#define CONCAT_(a, b) a##b
#define CONCAT(a, b) CONCAT_(a, b)

#define LIST_0(...)
#define LIST_1(M, x) M(x)
#define LIST_2(M, x, y) M(x), M(y)
#define LIST_3(M, x, y, z) M(x), M(y), M(z)
#define LIST_4(M, x, ...) M(x), LIST_3(M, __VA_ARGS__)
#define LIST_5(M, x, ...) M(x), LIST_4(M, __VA_ARGS__)
#define LIST_6(M, x, ...) M(x), LIST_5(M, __VA_ARGS__)
#define LIST_7(M, x, ...) M(x), LIST_6(M, __VA_ARGS__)
#define LIST_8(M, x, ...) M(x), LIST_7(M, __VA_ARGS__)
#define LIST_9(M, x, ...) M(x), LIST_8(M, __VA_ARGS__)
#define LIST(M, ...) CONCAT(LIST_, COUNT(__VA_ARGS__))(M, __VA_ARGS__)

#define DECLARE_PARAM(x) auto&amp;&amp; FIRST(x)

#define PICK_VALID(e1, e2, ...) overload(std::forward_as_tuple(LIST(SECOND, __VA_ARGS__)), \
                                         [] (LIST(DECLARE_PARAM, __VA_ARGS__)) -&gt; decltype(e1) {}, \
                                         [] (LIST(DECLARE_PARAM, __VA_ARGS__)) -&gt; decltype(e2) {})

// Test:
auto get_function() {return [] (int, int) {return &quot;&quot;;};}

auto o = PICK_VALID(f(1), f(1,1), (f, get_function()));

static_assert(std::is_same&lt;char const*, decltype(o)::type&gt;{});
</code></pre>
<p>In deinem Fall also</p>
<pre><code>auto somename1234 = PICK_VALID(f(get_source()), f(get_source(),1), (f, get_function()));
using value_type = decltype(somename1234)::type;
</code></pre>
<p>Oder man bastelt sich langweiligerweise eine angepasste Variante</p>
<pre><code>template &lt;typename F, typename... T1s, typename T2&gt;
auto detect(F&amp;&amp; f, std::tuple&lt;T1s...&gt;&amp;&amp;, T2&amp;&amp;) -&gt; decltype(f(std::declval&lt;T1s&gt;()...));
template &lt;typename F, typename T1, typename... T2s&gt;
auto detect(F&amp;&amp; f, T1&amp;&amp;, std::tuple&lt;T2s...&gt;&amp;&amp;) -&gt; decltype(f(std::declval&lt;T2s&gt;()...));

auto get_function() {return [] (int, int) {return &quot;&quot;;};}

using value_type = decltype(detect(get_function(), std::make_tuple(1),
                                                   std::make_tuple(1, 1)));
</code></pre>
<p>(Lässt sich auf beliebig viele Argument Sequenzen ausweiten).</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2491019</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2491019</guid><dc:creator><![CDATA[Columbo]]></dc:creator><pubDate>Mon, 21 Mar 2016 14:18:56 GMT</pubDate></item><item><title><![CDATA[Reply to Argumentzähler bei auto Parametern on Mon, 21 Mar 2016 14:52:32 GMT]]></title><description><![CDATA[<p>Die langweilige Variante gefällt mir, danke. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f603.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--grinning_face_with_big_eyes"
      title=":D"
      alt="😃"
    /></p>
<p>Bekommt man die beiden print_ Methoden auch noch irgendwie mit VS(2015) zum Laufen? (<a href="https://www.c-plusplus.net/forum/p2491013#2491013">https://www.c-plusplus.net/forum/p2491013#2491013</a>)<br />
VS beschwert sich mit</p>
<pre><code>C2535	&quot;unknown-type Printer_&lt;T&gt;::print_(U &amp;)&quot;: Memberfunktion bereits definiert oder deklariert
</code></pre>
<p>Hier noch ein Link zum Onlinecompiler:<br />
<a href="http://rextester.com/VCZAQ97017" rel="nofollow">http://rextester.com/VCZAQ97017</a></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2491024</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2491024</guid><dc:creator><![CDATA[KN4CK3R]]></dc:creator><pubDate>Mon, 21 Mar 2016 14:52:32 GMT</pubDate></item><item><title><![CDATA[Reply to Argumentzähler bei auto Parametern on Mon, 21 Mar 2016 14:56:36 GMT]]></title><description><![CDATA[<p>Siehe &quot;Workaround&quot; in meiner Antwort auf SO: <a href="http://stackoverflow.com/a/28204207/3647361" rel="nofollow">http://stackoverflow.com/a/28204207/3647361</a></p>
<p>Edit: Hier der Link: <a href="http://rextester.com/MLM54149" rel="nofollow">http://rextester.com/MLM54149</a><br />
Habe lediglich ein <code>, int = 0</code> angehängt.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2491025</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2491025</guid><dc:creator><![CDATA[Columbo]]></dc:creator><pubDate>Mon, 21 Mar 2016 14:56:36 GMT</pubDate></item><item><title><![CDATA[Reply to Argumentzähler bei auto Parametern on Mon, 21 Mar 2016 17:15:24 GMT]]></title><description><![CDATA[<p>perfekt, funktioniert!</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2491041</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2491041</guid><dc:creator><![CDATA[KN4CK3R]]></dc:creator><pubDate>Mon, 21 Mar 2016 17:15:24 GMT</pubDate></item></channel></rss>