<?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[C++ Talk Tipp &amp;amp; copy_on_write Code (dies ist keine Frage)]]></title><description><![CDATA[<p>Hi!</p>
<p>Inspiriert von Sean Parent's Vortrag &quot;<a href="http://www.youtube.com/watch?v=_BpMYeUFXv8" rel="nofollow">Value Semantics and Concepts-based Polymorphism</a>&quot;, den ich übrigens empfehlen kann, habe ich mich just-4-fun mal dran gesetzt, einen copy_on_write-Wrapper zu basteln, so wie er im Vortrag verwendet wurde. Das Ding ist mit Hilfe von shared_ptr und make_shared auch relativ easy umzusetzen und könnte hier ja irgendjemandem nutzen oder einen Denkanstoß verpassen.</p>
<p>Warum wieso weshalb copy_on_write? --&gt; Wertesemantik mit &quot;Sharing&quot; als Optimierung, effizientes Kopieren und Moven ist unabhängig von T möglich.</p>
<p>copy_on_write.hpp:</p>
<pre><code class="language-cpp">#ifndef COPY_ON_WRITE_HPP_INCLUDED
#define COPY_ON_WRITE_HPP_INCLUDED

#include &lt;cassert&gt;
#include &lt;type_traits&gt;
#include &lt;utility&gt;
#include &lt;memory&gt;

enum cow_dont_initialize_tag { cow_dont_initialize };

/// Copy-On-Write wrapper for a T object. It supports a &quot;null state&quot;
/// (you have to ask for it via an explicit std::move or the
/// cow_dont_initialize constructor parameter, though!).
template&lt;class T&gt;
class copy_on_write
{
public:

	/// Construct copy_on_write object without initializing a T object.
	/// The function initialized() will return false and you're not allowed
	/// to access the T object (because it doesn't exist!).
	explicit copy_on_write(cow_dont_initialize_tag) noexcept
	: ptr(nullptr)
	{}

	/// Construct copy_on_write object which holds a default-constructed T object
	copy_on_write()
	{
		static const std::shared_ptr&lt;T&gt; default_constructed = std::make_shared&lt;T&gt;();
		this-&gt;ptr = default_constructed;
	}

	/// Construct copy_on_write object to store a given T object initialized
	/// with an initializer_list.
	template&lt;class E
		,class=typename std::enable_if&lt;(
			std::is_constructible&lt;T,std::initializer_list&lt;E&gt;&gt;::value
		)&gt;::type
	&gt;
	copy_on_write(std::initializer_list&lt;E&gt; il)
	: ptr(std::make_shared&lt;T&gt;(il))
	{}

	/// Construct copy_on_write object to hold a T object constructed by
	/// forwarding parameters
	template&lt;class Arg, class...Args
		,class=typename std::enable_if&lt;(
			std::is_constructible&lt;T,Arg,Args...&gt;::value &amp;&amp;
			( sizeof...(Args)&gt;0 || // exclude copy/move ctor for copy_on_write
			  !std::is_same&lt;typename std::decay&lt;Arg&gt;::type,copy_on_write&lt;T&gt;&gt;::value )
		)&gt;::type
	&gt;
	copy_on_write(Arg&amp;&amp; arg, Args&amp;&amp;...args)
	: ptr(std::make_shared&lt;T&gt;(
		std::forward&lt;Arg&gt;(arg),
		std::forward&lt;Args&gt;(args)... ))
	{}

	/// copy ctor
	copy_on_write(copy_on_write const&amp; x) noexcept
	: ptr(x.ptr)
	{}

	/// move ctor
	copy_on_write(copy_on_write &amp;&amp; x) noexcept
	: ptr(std::move(x.ptr))
	{}

	// assignment
	copy_on_write&amp; operator=(copy_on_write temp) noexcept
	{ this-&gt;swap(temp); return *this; }

	void swap(copy_on_write&amp; that) noexcept
	{ this-&gt;ptr.swap(that.ptr); }

	friend void swap(copy_on_write&amp; a, copy_on_write&amp; b) noexcept
	{ a.swap(b); }

	// returns true if and only if this object owns an initialized T object
	bool initialized() const noexcept
	{ return ptr != nullptr; }

	// destroys the owned T object
	void destroy() noexcept
	{ ptr.reset(nullptr); }

	explicit operator bool() const noexcept
	{ return initialized(); }

	// read access ...
	T const&amp; read() const noexcept{ assert(initialized()); return *ptr; }
	T const&amp; operator*() const noexcept { assert(initialized()); return *ptr; }
	T const* operator-&gt;() const noexcept { assert(initialized()); return ptr.get(); }

	// write access ...
	T&amp; write()
	{
		assert(initialized());
		if (!ptr.unique()) uniqify();
		assert(ptr.unique());
		return *ptr;
	}

private:
	std::shared_ptr&lt;T&gt; ptr;

	void uniqify();
};

template&lt;class T&gt;
void copy_on_write&lt;T&gt;::uniqify()
{
	copy_on_write tmp (this-&gt;read());
	this-&gt;swap(tmp);
}

#endif
</code></pre>
<p>Simples, etwas realitätsfernes Beispiel:</p>
<pre><code class="language-cpp">#include &lt;cassert&gt;
#include &lt;vector&gt;
#include &quot;copy_on_write.hpp&quot;

using namespace std;

int main()
{
    copy_on_write&lt;vector&lt;int&gt;&gt; x = {2,3,5,7,11};
    copy_on_write&lt;vector&lt;int&gt;&gt; y = x;
    assert( &amp;x.read() == &amp;y.read() );
    y.write()[2] += 10;
    assert( &amp;x.read() != &amp;y.read() );
}
</code></pre>
<p>(kompiliert mit G++ 4.6.1 und C++0x-Schalter)</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/305528/c-talk-tipp-amp-copy_on_write-code-dies-ist-keine-frage</link><generator>RSS for Node</generator><lastBuildDate>Sat, 08 Aug 2026 19:59:12 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/305528.rss" rel="self" type="application/rss+xml"/><pubDate>Sun, 01 Jul 2012 16:15:28 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to C++ Talk Tipp &amp;amp; copy_on_write Code (dies ist keine Frage) on Sun, 01 Jul 2012 16:55:17 GMT]]></title><description><![CDATA[<p>Hi!</p>
<p>Inspiriert von Sean Parent's Vortrag &quot;<a href="http://www.youtube.com/watch?v=_BpMYeUFXv8" rel="nofollow">Value Semantics and Concepts-based Polymorphism</a>&quot;, den ich übrigens empfehlen kann, habe ich mich just-4-fun mal dran gesetzt, einen copy_on_write-Wrapper zu basteln, so wie er im Vortrag verwendet wurde. Das Ding ist mit Hilfe von shared_ptr und make_shared auch relativ easy umzusetzen und könnte hier ja irgendjemandem nutzen oder einen Denkanstoß verpassen.</p>
<p>Warum wieso weshalb copy_on_write? --&gt; Wertesemantik mit &quot;Sharing&quot; als Optimierung, effizientes Kopieren und Moven ist unabhängig von T möglich.</p>
<p>copy_on_write.hpp:</p>
<pre><code class="language-cpp">#ifndef COPY_ON_WRITE_HPP_INCLUDED
#define COPY_ON_WRITE_HPP_INCLUDED

#include &lt;cassert&gt;
#include &lt;type_traits&gt;
#include &lt;utility&gt;
#include &lt;memory&gt;

enum cow_dont_initialize_tag { cow_dont_initialize };

/// Copy-On-Write wrapper for a T object. It supports a &quot;null state&quot;
/// (you have to ask for it via an explicit std::move or the
/// cow_dont_initialize constructor parameter, though!).
template&lt;class T&gt;
class copy_on_write
{
public:

	/// Construct copy_on_write object without initializing a T object.
	/// The function initialized() will return false and you're not allowed
	/// to access the T object (because it doesn't exist!).
	explicit copy_on_write(cow_dont_initialize_tag) noexcept
	: ptr(nullptr)
	{}

	/// Construct copy_on_write object which holds a default-constructed T object
	copy_on_write()
	{
		static const std::shared_ptr&lt;T&gt; default_constructed = std::make_shared&lt;T&gt;();
		this-&gt;ptr = default_constructed;
	}

	/// Construct copy_on_write object to store a given T object initialized
	/// with an initializer_list.
	template&lt;class E
		,class=typename std::enable_if&lt;(
			std::is_constructible&lt;T,std::initializer_list&lt;E&gt;&gt;::value
		)&gt;::type
	&gt;
	copy_on_write(std::initializer_list&lt;E&gt; il)
	: ptr(std::make_shared&lt;T&gt;(il))
	{}

	/// Construct copy_on_write object to hold a T object constructed by
	/// forwarding parameters
	template&lt;class Arg, class...Args
		,class=typename std::enable_if&lt;(
			std::is_constructible&lt;T,Arg,Args...&gt;::value &amp;&amp;
			( sizeof...(Args)&gt;0 || // exclude copy/move ctor for copy_on_write
			  !std::is_same&lt;typename std::decay&lt;Arg&gt;::type,copy_on_write&lt;T&gt;&gt;::value )
		)&gt;::type
	&gt;
	copy_on_write(Arg&amp;&amp; arg, Args&amp;&amp;...args)
	: ptr(std::make_shared&lt;T&gt;(
		std::forward&lt;Arg&gt;(arg),
		std::forward&lt;Args&gt;(args)... ))
	{}

	/// copy ctor
	copy_on_write(copy_on_write const&amp; x) noexcept
	: ptr(x.ptr)
	{}

	/// move ctor
	copy_on_write(copy_on_write &amp;&amp; x) noexcept
	: ptr(std::move(x.ptr))
	{}

	// assignment
	copy_on_write&amp; operator=(copy_on_write temp) noexcept
	{ this-&gt;swap(temp); return *this; }

	void swap(copy_on_write&amp; that) noexcept
	{ this-&gt;ptr.swap(that.ptr); }

	friend void swap(copy_on_write&amp; a, copy_on_write&amp; b) noexcept
	{ a.swap(b); }

	// returns true if and only if this object owns an initialized T object
	bool initialized() const noexcept
	{ return ptr != nullptr; }

	// destroys the owned T object
	void destroy() noexcept
	{ ptr.reset(nullptr); }

	explicit operator bool() const noexcept
	{ return initialized(); }

	// read access ...
	T const&amp; read() const noexcept{ assert(initialized()); return *ptr; }
	T const&amp; operator*() const noexcept { assert(initialized()); return *ptr; }
	T const* operator-&gt;() const noexcept { assert(initialized()); return ptr.get(); }

	// write access ...
	T&amp; write()
	{
		assert(initialized());
		if (!ptr.unique()) uniqify();
		assert(ptr.unique());
		return *ptr;
	}

private:
	std::shared_ptr&lt;T&gt; ptr;

	void uniqify();
};

template&lt;class T&gt;
void copy_on_write&lt;T&gt;::uniqify()
{
	copy_on_write tmp (this-&gt;read());
	this-&gt;swap(tmp);
}

#endif
</code></pre>
<p>Simples, etwas realitätsfernes Beispiel:</p>
<pre><code class="language-cpp">#include &lt;cassert&gt;
#include &lt;vector&gt;
#include &quot;copy_on_write.hpp&quot;

using namespace std;

int main()
{
    copy_on_write&lt;vector&lt;int&gt;&gt; x = {2,3,5,7,11};
    copy_on_write&lt;vector&lt;int&gt;&gt; y = x;
    assert( &amp;x.read() == &amp;y.read() );
    y.write()[2] += 10;
    assert( &amp;x.read() != &amp;y.read() );
}
</code></pre>
<p>(kompiliert mit G++ 4.6.1 und C++0x-Schalter)</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2228942</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2228942</guid><dc:creator><![CDATA[krümelkacker]]></dc:creator><pubDate>Sun, 01 Jul 2012 16:55:17 GMT</pubDate></item><item><title><![CDATA[Reply to C++ Talk Tipp &amp;amp; copy_on_write Code (dies ist keine Frage) on Sun, 01 Jul 2012 16:28:37 GMT]]></title><description><![CDATA[<p>krümelkacker schrieb:</p>
<blockquote>
<p>Inspiriert von Sean Parent's Vortrag &quot;<a href="http://www.youtube.com/watch?v=_BpMYeUFXv8" rel="nofollow">Value Semantics and Concepts-based Polymorphism</a>&quot;</p>
</blockquote>
<p>Gibts das auch als Text? Ich kann mit Videos nichts anfangen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2228950</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2228950</guid><dc:creator><![CDATA[Mechanics]]></dc:creator><pubDate>Sun, 01 Jul 2012 16:28:37 GMT</pubDate></item><item><title><![CDATA[Reply to C++ Talk Tipp &amp;amp; copy_on_write Code (dies ist keine Frage) on Sun, 01 Jul 2012 16:35:27 GMT]]></title><description><![CDATA[<p>Ja:<br />
<a href="https://github.com/boostcon/cppnow_presentations_2012/tree/master/fri/value_semantics" rel="nofollow">https://github.com/boostcon/cppnow_presentations_2012/tree/master/fri/value_semantics</a></p>
<p>Da gibt's sogar Quellcode. Allerdings hat Sean Parent hier nicht erkannt, dass man sich das Leben da mit shared_ptr für die copy_on_write-Implementierung etwas einfacher machen kann. Dann erübrigt sich das auch mit der thread-sicheren Referenzzählung, die ja in shared_ptr schon eingebaut ist. <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>
]]></description><link>https://www.c-plusplus.net/forum/post/2228955</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2228955</guid><dc:creator><![CDATA[krümelkacker]]></dc:creator><pubDate>Sun, 01 Jul 2012 16:35:27 GMT</pubDate></item></channel></rss>