<?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[SFINAE - IsExplicitConvertible und IsDefaultConstructible]]></title><description><![CDATA[<p>Hallo,</p>
<p>also zunächst mal würde ich gerne wissen, ob es allgemein korrekt ist (nach allen drei mehr oder weniger aktuellen Standards) einen Laufzeitausdruck auf Richtigkeit zu prüfen, indem man das folgende Konstrukt verwendet:</p>
<pre><code>template&lt;typename T&gt;
		static NoType Check(...);
		template&lt;typename T&gt;
		static YesType Check(SizeToType&lt;sizeof(Ausdruck)&gt;*);
</code></pre>
<p>Denn seltsamerweise funktionieren solche Konstrukte teilweise, teilweise hingegen auch nicht. Hier knüpft auch meine nächste Frage gerade an. Ist das Folgende korrekt?</p>
<pre><code>template&lt;typename From, typename To&gt;
	class IsExplicitConvertible
	{
		template&lt;typename FromT, typename ToT&gt;
		static NoType Check(...);
		template&lt;typename FromT, typename ToT&gt;
		static YesType Check(SizeToType&lt;sizeof(static_cast&lt;ToT&gt;(DeclVal&lt;FromT&gt;()))&gt;*);

	public:
		static const bool Value = sizeof(Check&lt;From, To&gt;(0)) == sizeof(YesType);
	};
</code></pre>
<p>Zur Erklärung kurz falls die Bezeichner nicht selbsterklärend genug sind:</p>
<ul>
<li><code>SizeToType</code> ist etwa dasselbe wie <code>template&lt;std::size_t Size&gt; using SizeToType = std::integral_constant&lt;std::size_t, Size&gt;;</code></li>
<li><code>NoType</code> und <code>YesType</code> sind garantiert unterschiedich grosse Typen</li>
</ul>
<p>Der Code zu <code>IsExplicitConvertible</code> funktioniert auf MSVC nicht, auf GCC 4.8.1 hingegen schon. Wäre er also eigentlich korrekt?</p>
<p>Nun zu einem Code, der sowohl auf MSVC als auch auf GCC nicht das gewünschte Ergebnis liefert:</p>
<pre><code>template&lt;typename T&gt;
		class IsDefaultConstructible
		{
			template&lt;typename U&gt;
			static NoType Check(...);
			template&lt;typename U&gt;
			static YesType Check(SizeToType&lt;sizeof(U())&gt;*);

		public:
			static const bool Value = sizeof(Check&lt;T&gt;(0)) == sizeof(YesType);
		};
</code></pre>
<p>Interessant ist jedoch, dass dieser Code bei MSVC bei allen Typen in <code>true</code> resultiert, bei GCC jedoch in <code>false</code> . Wäre der Code korrekt?</p>
<p>Hinzuzufügen ist vielleicht noch, dass bei MSVC die meisten Klassen aus <code>&lt;type_traits&gt;</code> mit Intrinsics implementiert wurden.</p>
<p>Gruss.</p>
<p>Edit:<br />
Hier ist das Minimalbeispiel:</p>
<pre><code>#include &lt;iostream&gt;

typedef std::size_t SizeType;

template&lt;typename T&gt;
struct Identity
{
	typedef T Type;
};

typedef Identity&lt;char(&amp;)[1]&gt;::Type NoType;
typedef Identity&lt;char(&amp;)[2]&gt;::Type YesType;

template&lt;typename T, T Val&gt;
struct IntegralConstant : public Identity&lt;IntegralConstant&lt;T, Val&gt; &gt;
{
	typedef T ValueType;

#ifdef Lib_Cpp11
	static constexpr ValueType Value = Val;
	constexpr operator ValueType() const
	{
		return this-&gt;Value;
	}
#else // Lib_Cpp11
	static const ValueType Value = Val;
	operator ValueType() const
	{
		return this-&gt;Value;
	}
#endif // Lib_Cpp11
};

template&lt;SizeType Val&gt;
struct SizeToType : public IntegralConstant&lt;SizeType, Val&gt;
{
};

template&lt;bool Val&gt;
struct BoolToType : public IntegralConstant&lt;bool, Val&gt;
{
};

template&lt;typename T&gt;
T&amp; DeclVal();

namespace Detail
{
	template&lt;typename From, typename To&gt;
	class IsExplicitConvertible
	{
		template&lt;typename FromT, typename ToT&gt;
		static NoType Check(...);
		template&lt;typename FromT, typename ToT&gt;
		static YesType Check(SizeToType&lt;sizeof(static_cast&lt;ToT&gt;(DeclVal&lt;FromT&gt;()))&gt;*);

	public:
		static const bool Value = sizeof(Check&lt;From, To&gt;(0)) == sizeof(YesType);
	};

	template&lt;typename T&gt; 
	class IsDefaultConstructible 
	{ 
		template&lt;typename U&gt; 
		static NoType Check(...); 
		template&lt;typename U&gt; 
		static YesType Check(SizeToType&lt;sizeof(U())&gt;*); 

	public: 
		static const bool Value = sizeof(Check&lt;T&gt;(0)) == sizeof(YesType); 
	};
}

template&lt;typename From, typename To&gt;
struct IsExplicitConvertible : public BoolToType&lt;Detail::IsExplicitConvertible&lt;From, To&gt;::Value&gt;
{
};

template&lt;typename T&gt;
struct IsDefaultConstructible : public BoolToType&lt;Detail::IsDefaultConstructible&lt;T&gt;::Value&gt;
{
};

struct Foo1
{
	explicit Foo1(int);

	operator char();
};

class Foo2
{
	Foo2();
};

struct Foo3
{
};

int main()
{
	std::cout &lt;&lt; IsExplicitConvertible&lt;int, float&gt;::Value &lt;&lt; '\n';		// Sollte 1 sein
	std::cout &lt;&lt; IsExplicitConvertible&lt;int, Foo1&gt;::Value &lt;&lt; '\n';		// Sollte 1 sein
	std::cout &lt;&lt; IsExplicitConvertible&lt;float, Foo1&gt;::Value &lt;&lt; '\n';		// Sollte 1 sein
	std::cout &lt;&lt; IsExplicitConvertible&lt;Foo1, char&gt;::Value &lt;&lt; '\n';		// Sollte 1 sein
	std::cout &lt;&lt; IsExplicitConvertible&lt;Foo1, double&gt;::Value &lt;&lt; '\n';	// Sollte 1 sein
	std::cout &lt;&lt; IsExplicitConvertible&lt;bool, Foo2&gt;::Value &lt;&lt; '\n';		// Sollte 0 sein
	std::cout &lt;&lt; IsExplicitConvertible&lt;int, void*&gt;::Value &lt;&lt; '\n';		// Sollte 0 sein
	std::cout &lt;&lt; '\n';
	std::cout &lt;&lt; IsDefaultConstructible&lt;int&gt;::Value &lt;&lt; '\n';			// Sollte 1 sein
	std::cout &lt;&lt; IsDefaultConstructible&lt;Foo1&gt;::Value &lt;&lt; '\n';			// Sollte 0 sein
	std::cout &lt;&lt; IsDefaultConstructible&lt;Foo2&gt;::Value &lt;&lt; '\n';			// Sollte 0 sein
	std::cout &lt;&lt; IsDefaultConstructible&lt;Foo3&gt;::Value &lt;&lt; '\n';			// Sollte 1 sein
}
</code></pre>
<p><a href="http://ideone.com/aFlCpm" rel="nofollow">http://ideone.com/aFlCpm</a></p>
<p>Edit 2:<br />
Den Blödsinn rausgelöscht. <code>void</code> ist natürlich nicht in Default-Konstruierbare Typen konvertierbar. Ich dachte, dass das mit dem Übergeben eines <code>void</code> s (wie bei Funktionen) auch bei Konstruktoren funktioniert, dem ist aber nicht so.</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/327733/sfinae-isexplicitconvertible-und-isdefaultconstructible</link><generator>RSS for Node</generator><lastBuildDate>Wed, 08 Jul 2026 22:44:42 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/327733.rss" rel="self" type="application/rss+xml"/><pubDate>Mon, 01 Sep 2014 08:51:01 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to SFINAE - IsExplicitConvertible und IsDefaultConstructible on Mon, 01 Sep 2014 10:06:31 GMT]]></title><description><![CDATA[<p>Hallo,</p>
<p>also zunächst mal würde ich gerne wissen, ob es allgemein korrekt ist (nach allen drei mehr oder weniger aktuellen Standards) einen Laufzeitausdruck auf Richtigkeit zu prüfen, indem man das folgende Konstrukt verwendet:</p>
<pre><code>template&lt;typename T&gt;
		static NoType Check(...);
		template&lt;typename T&gt;
		static YesType Check(SizeToType&lt;sizeof(Ausdruck)&gt;*);
</code></pre>
<p>Denn seltsamerweise funktionieren solche Konstrukte teilweise, teilweise hingegen auch nicht. Hier knüpft auch meine nächste Frage gerade an. Ist das Folgende korrekt?</p>
<pre><code>template&lt;typename From, typename To&gt;
	class IsExplicitConvertible
	{
		template&lt;typename FromT, typename ToT&gt;
		static NoType Check(...);
		template&lt;typename FromT, typename ToT&gt;
		static YesType Check(SizeToType&lt;sizeof(static_cast&lt;ToT&gt;(DeclVal&lt;FromT&gt;()))&gt;*);

	public:
		static const bool Value = sizeof(Check&lt;From, To&gt;(0)) == sizeof(YesType);
	};
</code></pre>
<p>Zur Erklärung kurz falls die Bezeichner nicht selbsterklärend genug sind:</p>
<ul>
<li><code>SizeToType</code> ist etwa dasselbe wie <code>template&lt;std::size_t Size&gt; using SizeToType = std::integral_constant&lt;std::size_t, Size&gt;;</code></li>
<li><code>NoType</code> und <code>YesType</code> sind garantiert unterschiedich grosse Typen</li>
</ul>
<p>Der Code zu <code>IsExplicitConvertible</code> funktioniert auf MSVC nicht, auf GCC 4.8.1 hingegen schon. Wäre er also eigentlich korrekt?</p>
<p>Nun zu einem Code, der sowohl auf MSVC als auch auf GCC nicht das gewünschte Ergebnis liefert:</p>
<pre><code>template&lt;typename T&gt;
		class IsDefaultConstructible
		{
			template&lt;typename U&gt;
			static NoType Check(...);
			template&lt;typename U&gt;
			static YesType Check(SizeToType&lt;sizeof(U())&gt;*);

		public:
			static const bool Value = sizeof(Check&lt;T&gt;(0)) == sizeof(YesType);
		};
</code></pre>
<p>Interessant ist jedoch, dass dieser Code bei MSVC bei allen Typen in <code>true</code> resultiert, bei GCC jedoch in <code>false</code> . Wäre der Code korrekt?</p>
<p>Hinzuzufügen ist vielleicht noch, dass bei MSVC die meisten Klassen aus <code>&lt;type_traits&gt;</code> mit Intrinsics implementiert wurden.</p>
<p>Gruss.</p>
<p>Edit:<br />
Hier ist das Minimalbeispiel:</p>
<pre><code>#include &lt;iostream&gt;

typedef std::size_t SizeType;

template&lt;typename T&gt;
struct Identity
{
	typedef T Type;
};

typedef Identity&lt;char(&amp;)[1]&gt;::Type NoType;
typedef Identity&lt;char(&amp;)[2]&gt;::Type YesType;

template&lt;typename T, T Val&gt;
struct IntegralConstant : public Identity&lt;IntegralConstant&lt;T, Val&gt; &gt;
{
	typedef T ValueType;

#ifdef Lib_Cpp11
	static constexpr ValueType Value = Val;
	constexpr operator ValueType() const
	{
		return this-&gt;Value;
	}
#else // Lib_Cpp11
	static const ValueType Value = Val;
	operator ValueType() const
	{
		return this-&gt;Value;
	}
#endif // Lib_Cpp11
};

template&lt;SizeType Val&gt;
struct SizeToType : public IntegralConstant&lt;SizeType, Val&gt;
{
};

template&lt;bool Val&gt;
struct BoolToType : public IntegralConstant&lt;bool, Val&gt;
{
};

template&lt;typename T&gt;
T&amp; DeclVal();

namespace Detail
{
	template&lt;typename From, typename To&gt;
	class IsExplicitConvertible
	{
		template&lt;typename FromT, typename ToT&gt;
		static NoType Check(...);
		template&lt;typename FromT, typename ToT&gt;
		static YesType Check(SizeToType&lt;sizeof(static_cast&lt;ToT&gt;(DeclVal&lt;FromT&gt;()))&gt;*);

	public:
		static const bool Value = sizeof(Check&lt;From, To&gt;(0)) == sizeof(YesType);
	};

	template&lt;typename T&gt; 
	class IsDefaultConstructible 
	{ 
		template&lt;typename U&gt; 
		static NoType Check(...); 
		template&lt;typename U&gt; 
		static YesType Check(SizeToType&lt;sizeof(U())&gt;*); 

	public: 
		static const bool Value = sizeof(Check&lt;T&gt;(0)) == sizeof(YesType); 
	};
}

template&lt;typename From, typename To&gt;
struct IsExplicitConvertible : public BoolToType&lt;Detail::IsExplicitConvertible&lt;From, To&gt;::Value&gt;
{
};

template&lt;typename T&gt;
struct IsDefaultConstructible : public BoolToType&lt;Detail::IsDefaultConstructible&lt;T&gt;::Value&gt;
{
};

struct Foo1
{
	explicit Foo1(int);

	operator char();
};

class Foo2
{
	Foo2();
};

struct Foo3
{
};

int main()
{
	std::cout &lt;&lt; IsExplicitConvertible&lt;int, float&gt;::Value &lt;&lt; '\n';		// Sollte 1 sein
	std::cout &lt;&lt; IsExplicitConvertible&lt;int, Foo1&gt;::Value &lt;&lt; '\n';		// Sollte 1 sein
	std::cout &lt;&lt; IsExplicitConvertible&lt;float, Foo1&gt;::Value &lt;&lt; '\n';		// Sollte 1 sein
	std::cout &lt;&lt; IsExplicitConvertible&lt;Foo1, char&gt;::Value &lt;&lt; '\n';		// Sollte 1 sein
	std::cout &lt;&lt; IsExplicitConvertible&lt;Foo1, double&gt;::Value &lt;&lt; '\n';	// Sollte 1 sein
	std::cout &lt;&lt; IsExplicitConvertible&lt;bool, Foo2&gt;::Value &lt;&lt; '\n';		// Sollte 0 sein
	std::cout &lt;&lt; IsExplicitConvertible&lt;int, void*&gt;::Value &lt;&lt; '\n';		// Sollte 0 sein
	std::cout &lt;&lt; '\n';
	std::cout &lt;&lt; IsDefaultConstructible&lt;int&gt;::Value &lt;&lt; '\n';			// Sollte 1 sein
	std::cout &lt;&lt; IsDefaultConstructible&lt;Foo1&gt;::Value &lt;&lt; '\n';			// Sollte 0 sein
	std::cout &lt;&lt; IsDefaultConstructible&lt;Foo2&gt;::Value &lt;&lt; '\n';			// Sollte 0 sein
	std::cout &lt;&lt; IsDefaultConstructible&lt;Foo3&gt;::Value &lt;&lt; '\n';			// Sollte 1 sein
}
</code></pre>
<p><a href="http://ideone.com/aFlCpm" rel="nofollow">http://ideone.com/aFlCpm</a></p>
<p>Edit 2:<br />
Den Blödsinn rausgelöscht. <code>void</code> ist natürlich nicht in Default-Konstruierbare Typen konvertierbar. Ich dachte, dass das mit dem Übergeben eines <code>void</code> s (wie bei Funktionen) auch bei Konstruktoren funktioniert, dem ist aber nicht so.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2415624</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2415624</guid><dc:creator><![CDATA[Fytch]]></dc:creator><pubDate>Mon, 01 Sep 2014 10:06:31 GMT</pubDate></item><item><title><![CDATA[Reply to SFINAE - IsExplicitConvertible und IsDefaultConstructible on Mon, 01 Sep 2014 09:12:40 GMT]]></title><description><![CDATA[<p>Mir fehlt das lauffähige Programm zum Testen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2415626</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2415626</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Mon, 01 Sep 2014 09:12:40 GMT</pubDate></item><item><title><![CDATA[Reply to SFINAE - IsExplicitConvertible und IsDefaultConstructible on Mon, 01 Sep 2014 09:19:09 GMT]]></title><description><![CDATA[<blockquote>
<p>Wäre er also eigentlich korrekt?</p>
</blockquote>
<p>Er ist korrekt.</p>
<blockquote>
<p>Wäre der Code korrekt?</p>
</blockquote>
<p>Nein, der zweite Code ist ganz subtil falsch.</p>
<pre><code>sizeof(U())
</code></pre>
<p><code>U()</code> ist ein Funktionstyp. Und man darf <code>sizeof</code> nicht auf Funktionstypen anwenden.</p>
<p>§5.3.3/1 schrieb:</p>
<blockquote>
<p>The <code>sizeof</code> operator shall not be applied to an expression that has function or incomplete type</p>
</blockquote>
<p>Daher wird die Instantiierung des zweiten Funktionstemplates immer in einem deduction failure enden.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2415628</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2415628</guid><dc:creator><![CDATA[Columbo]]></dc:creator><pubDate>Mon, 01 Sep 2014 09:19:09 GMT</pubDate></item><item><title><![CDATA[Reply to SFINAE - IsExplicitConvertible und IsDefaultConstructible on Mon, 01 Sep 2014 09:40:38 GMT]]></title><description><![CDATA[<p>gcc hat übrigens den sutilen fehler angewarnt.<br />
&quot;invalid application of 'sizeof' to a function type&quot;</p>
<p>Und dann kapiert gcc Folgendes:</p>
<pre><code>static YesType Check(SizeToType&lt;sizeof((U()))&gt;*);
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2415632</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2415632</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Mon, 01 Sep 2014 09:40:38 GMT</pubDate></item><item><title><![CDATA[Reply to SFINAE - IsExplicitConvertible und IsDefaultConstructible on Mon, 01 Sep 2014 09:49:38 GMT]]></title><description><![CDATA[<blockquote>
<p>gcc hat übrigens den sutilen fehler angewarnt.</p>
</blockquote>
<p>Kann ich nicht nachvollziehen. Welcher Code?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2415634</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2415634</guid><dc:creator><![CDATA[Columbo]]></dc:creator><pubDate>Mon, 01 Sep 2014 09:49:38 GMT</pubDate></item><item><title><![CDATA[Reply to SFINAE - IsExplicitConvertible und IsDefaultConstructible on Mon, 01 Sep 2014 09:52:58 GMT]]></title><description><![CDATA[<p>volkard schrieb:</p>
<blockquote>
<p>Mir fehlt das lauffähige Programm zum Testen.</p>
</blockquote>
<p>Ups, sorry. Ich hab's ergänzt.</p>
<p>Arcoth schrieb:</p>
<blockquote>
<p><code>U()</code> ist ein Funktionstyp.</p>
</blockquote>
<p><img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f62e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_with_open_mouth"
      title=":open_mouth:"
      alt="😮"
    /> Wow, das ist gemein.</p>
<p>volkard schrieb:</p>
<blockquote>
<p>Und dann kapiert gcc Folgendes:</p>
</blockquote>
<p>Funktioniert das, weil man Typen nicht in ein Klammerpaar setzen darf, Werte aber schon? Cooler Trick.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2415635</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2415635</guid><dc:creator><![CDATA[Fytch]]></dc:creator><pubDate>Mon, 01 Sep 2014 09:52:58 GMT</pubDate></item><item><title><![CDATA[Reply to SFINAE - IsExplicitConvertible und IsDefaultConstructible on Mon, 01 Sep 2014 09:55:18 GMT]]></title><description><![CDATA[<p>Arcoth schrieb:</p>
<blockquote>
<blockquote>
<p>gcc hat übrigens den sutilen fehler angewarnt.</p>
</blockquote>
<p>Kann ich nicht nachvollziehen. Welcher Code?</p>
</blockquote>
<pre><code>cout&lt;&lt;sizeof(Foo1())&lt;&lt;'\n';
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2415636</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2415636</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Mon, 01 Sep 2014 09:55:18 GMT</pubDate></item></channel></rss>