tag:blogger.com,1999:blog-61145691104360588172016-09-26T11:08:54.774+02:00litb's BlogJohannes (litb)http://www.blogger.com/profile/07110437420755294372noreply@blogger.comBlogger4125tag:blogger.com,1999:blog-6114569110436058817.post-88606458783828061462011-12-30T00:10:00.003+01:002011-12-31T17:04:11.587+01:00Access to private members: Safer nastiness.In one of my previous posts I showed some code that accesses a private member, that now has been posted on the boost mailing list as a possible utility for boost serialization to access private attributes (OH MY, I had no idea such a thing actually could have uses!).<br />
<p>I realized that it would be beneficial to have an alternative implementation because the previous code suffered from the Static Initialization Order Fiasco. The following code does not suffer from that problem anymore:<br />
<pre class="prettyprint">template&lt;typename Tag, typename Tag::type M&gt;
struct Rob {
friend typename Tag::type get(Tag) {
return M;
}
};</pre>This defines a friend function that can be called by ADL using the tag type.<br />
<pre class="prettyprint">// use
struct A {
A(int a):a(a) { }
private:
int a;
};
// tag used to access A::a
struct A_f {
typedef int A::*type;
friend type get(A_f);
};
template struct Rob&lt;A_f, &A::a&gt;;
int main() {
A a(42);
std::cout &lt;&lt; "proof: " &lt;&lt; a.*get(A_f()) &lt;&lt; std::endl;
}</pre>Note that the explicit declaration of "get" inside of "A_f" is important, because we want "get" to be visible to ADL, and the rob template specialization is not an associated class of "A_f" (we could have declared it globally too, if we wanted, but then it would be visible for anyone). To overcome that, we could introduce some utility class we derive from:<br />
<pre class="prettyprint">template&lt;typename Tag, typename Member&gt;
struct TagBase {
typedef Member type;
friend type get(Tag);
};</pre></p>The definition of a Tag then becomes very simple<br />
<pre class="prettyprint">struct A_f : TagBase&lt;A_f, int A::*&gt; { };</pre>Unfortunately with the TagBase, GCC spits out a warning about the "friend type get(Tag)" that it declares a non-template function. The warning can be ignored, but it's annoying :).<br />
<br />
Hope you enjoyed!Johannes (litb)http://www.blogger.com/profile/07110437420755294372noreply@blogger.com10tag:blogger.com,1999:blog-6114569110436058817.post-86474083279968171152010-11-27T03:42:00.000+01:002010-11-27T04:12:39.105+01:00Fun with switch statementsSince my coworker proudly told me about some switch macro he created for himself with C that can process strings, I thought I wanted to do that too, but with C++. Here is what I ended up with.
<pre class="prettyprint">#include &lt;boost/typeof/typeof.hpp&gt;
#include &lt;cassert&gt;
/* Store a value of type V */
template&lt;typename V&gt;
struct S {
operator int() { return -1; }
S(V const&amp; data):data(data), matched(false) { }
V data;
bool matched;
};
#define sswitch(V) \
switch(S&lt;BOOST_TYPEOF(V)&gt; _s_ = V) \
case -1: { if(0)
#define scase(V) \
} if(!(_s_.matched || _s_.data == V)) ; else \
if(!(_s_.matched = true)) ; else { case __LINE__
#define sdefault() \
} default
#define snodefault(MSG) \
} do { assert(!MSG); __builtin_unreachable(); } while(0)
</pre>
That looks pretty weird! What are its drawbacks?
<ul>
<li>A default case must always be present and <i>must</i> be put last</li>
<li>Can't put a block around several cases, so <code>sswitch</code> is incompatible to
<a href="http://en.wikipedia.org/wiki/Duffs_device">Duffs device</a>.</li>
<li>The to-be-switched value is always copied - there is no automatic deduction for lvalues
such that they would use references and that only rvalues would be copied</li>
</ul>
On the goodness sides, <code>sswitch</code> can use native break keywords with the expected semantics, works with any type (not just strings) and also supports fall-through like the built-in switch.
Here is how it can be used.
<pre class="prettyprint"> sswitch(s) {
scase(&quot;foo&quot;): {
std::cout &lt;&lt; &quot;s is foo&quot; &lt;&lt; std::endl;
break; // could fall-through if we wanted
}
// supports brace-less style too
scase(&quot;bar&quot;):
std::cout &lt;&lt; &quot;s is bar&quot; &lt;&lt; std::endl;
break;
// default must be at the end
sdefault():
std::cout &lt;&lt; &quot;neither of those!&quot; &lt;&lt; std::endl;
break;
}
</pre>
Notice that since we insert extra braces between each case label (to prevent the code in between to be executed if we haven't hit a label yet), we can't use a plain "default:" at the end, as would be desired by me.
We can jump inside if we want
<pre class="prettyprint"> sswitch(s) {
test:
std::cout &lt;&lt; &quot;this will be output after foo/bar!&quot; &lt;&lt; std::endl;
break;
scase(&quot;foo&quot;): {
std::cout &lt;&lt; &quot;s is foo&quot; &lt;&lt; std::endl;
goto test;
}
// supports brace-less style too
scase(&quot;bar&quot;):
std::cout &lt;&lt; &quot;s is bar&quot; &lt;&lt; std::endl;
goto test;
// default must be at the end
snodefault(&quot;neither foo nor bar!?&quot;);
}
</pre>
<p>
Please tell me what you think about it and whether you find any problem! Hope you like this little helper!</p>Johannes (litb)http://www.blogger.com/profile/07110437420755294372noreply@blogger.com7tag:blogger.com,1999:blog-6114569110436058817.post-60554944201371775572010-07-03T03:59:00.000+02:002010-07-04T21:33:16.989+02:00Access to private members. That's easy!<p>So, always thought that it's impossible without undefined behavior to access private members of arbitrary classes without being friend.</p>
<p>
Today I noticed I've been horribly wrong, after reading some insightful commit to the clang compiler, that enabled it to allow explicit instantiation to disregard accessibilities, as per the Standard. This enables us to access private members of others. As an experiment, I created some class templates
<pre class="prettyprint">template&lt;typename Tag&gt;
struct result {
/* export it ... */
typedef typename Tag::type type;
static type ptr;
};
template&lt;typename Tag&gt;
typename result&lt;Tag&gt;::type result&lt;Tag&gt;::ptr;
template&lt;typename Tag, typename Tag::type p&gt;
struct rob : result&lt;Tag&gt; {
/* fill it ... */
struct filler {
filler() { result&lt;Tag&gt;::ptr = p; }
};
static filler filler_obj;
};
template&lt;typename Tag, typename Tag::type p&gt;
typename rob&lt;Tag, p&gt;::filler rob&lt;Tag, p&gt;::filler_obj;
</pre></p>
<p>
So, how is it used? Let's have an example
<pre class="prettyprint">struct A {
private:
void f() {
std::cout &lt;&lt; "proof!" &lt;&lt; std::endl;
}
};
struct Af { typedef void(A::*type)(); };
template class rob&lt;Af, &amp;A::f&gt;;
</pre></p>
<p>
Ah, that's all to expose poor A's "f" member. Now anyone can use them using the member pointer snytax, as does the main function below
<pre class="prettyprint">int main() {
A a;
(a.*result&lt;Af&gt;::ptr)();
}
</pre></p>
<p>
Of course, as <a href="http://www.gotw.ca/gotw/076.htm">Herb Sutter told us</a>, don't do these things in real code.</p>Johannes (litb)http://www.blogger.com/profile/07110437420755294372noreply@blogger.com16tag:blogger.com,1999:blog-6114569110436058817.post-80222218109680529432008-11-01T06:38:00.000+01:002010-07-04T21:53:29.835+02:00My new blog and a Pacman surprise<p>Hello there.</p>
<p>So now I've read many blogs out there. And I think it's time that I also own some blogs about what I'm doing with my spare time and whatnot :P So I came across blogger.com and thought it would be a good idea to get my hands dirty and create one. So here we are.</p>
<p>
First of all I want to tell you that pacman.d mirrorlist is sometimes really not ordered all that well :P So after waiting another round of minute for the <a href="http://www.videolan.org/">VLC</a> package to download completely, I figured it would be the best to just sit down and write this script:
<pre class="prettyprint">
tmpf=$(mktemp)
trap &quot;rm -f $tmpf; exit&quot; INT TERM
gawk '
/#?Server =/ {
host = gensub(/^[^:]+:\/\/([^/]+).*/, &quot;\\1&quot;, 1, $3)
print host, $0
}' /etc/pacman.d/mirrorlist |
while read host line; do
echo &quot;trying to ping '$host'&quot; &gt;/dev/stderr
timed=$(ping -i 0.3 -c 1 -W 1 -n -q $host 2&gt;/dev/null |
tail -n1 |
gawk '{ print $4 }' |
cut -f2 -d/)
[ x != x$timed ] &amp;&amp; echo $timed ${line%#*};
done | LC_ALL=C sort -n |
while read crap remains; do
echo $remains \# $crap ms;
done &gt; $tmpf
echo 'the following was created: '
cat $tmpf
echo -e '\nwant me to use it? (y|n)'
read reply
if [ x$reply = xy ]; then
mv $tmpf /etc/pacman.d/mirrorlist
else
rm -f $tmpf
fi
</pre>
</p>
<p>
What does it do? Well, it basicially finds out the currently best order for the mirrorlist file, so that the fastest mirror is at the top. After running it, I was really impressed about the speed of pacman. It rushed through like a tiger :P</p>Johannes (litb)http://www.blogger.com/profile/07110437420755294372noreply@blogger.com5