Saturday, 17 May 2014

Named function arguments for C++, again

This is probably/maybe the final installment on my inoffical series on emulating named function parameters in C++ (see here and here). This time, I was inspired by the technique I spotted in the sqlpp11 library (see also the talk here or the slides here).

Want to see it in action? You can call functions like that:
// 2 string parameters
test_func(first_name = "alfa", second_name = "beta");
      
// a string and a bool parameter
test_func_bool("zeta", enable_widgets = true);  

//test_func("alfa"); -- too much, not supported!  
The downside is, that you always must use the names of parameters, i.e. you cannot fall back to positional usage. This is intentional, as to keep the implementation as simple as possible. It's doable, of course, but for what reason? If you don't need name parameter at a given position, don't use it.

So how does the implementation work? It's rather minimal, as ot doesn't try to do all the thing possible. Call me non-genius, but such small code pleases me. Basically, the name argument instance will return an asignment proxy, which remembers the value assigned to it. You say it's unnecessary? And you are totally right, it's only there as to tie a name to the given parameter!
template<typename Lhs, typename Rhs>
struct assignment_t
{
  using lhs_t = Lhs;
  using rhs_t = Rhs;
  lhs_t _lhs;
  rhs_t _rhs;   
};
 
template<typename T>
struct named_arg_t
{
  using type = assignment_t<named_arg_t, T>;
  auto operator=(T arg)
    -> assignment_t<named_arg_t, T>
  {
    return { {}, arg };
  }    
};
try it online: http://www.compileonline.com, you can find the complete code here.

How do you define functions using the named parameters?
// usage string:
named_arg_t<std::string> first_name{};
named_arg_t<std::string> second_name{};
 
void test_func(named_arg_t<std::string>::type first_name, named_arg_t<std::string>::type second_name) 
{
  auto firstname_val = first_name._rhs;
  auto secondname_val = second_name._rhs;
  std::cout << "first name=" << firstname_val 
            << ", second name=" << secondname_val 
            << std::endl;
}
 
// usage bool:
named_arg_t<bool> enable_widgets{};
 
void test_func_bool(const std::string& name, named_arg_t<bool>::type enable_widgets)
{
  if(enable_widgets._rhs)    
  {
    std::cout << "enable widgets for: " << name << std::endl; 
  }
}
You see, there's another caveat - the parameters are still positional, you cannot call the function like that:
// 2 string parameters
test_func(second_name = "beta", first_name = "alfa");
because C++ knows only positional pameters.

I think, this usage is intuitive - you express your wish to have a named parameter (name_arg_t<>) of a gven type (string or bool). Then you acces the parameter's value using a getter in the function - I think it's a minor inconvenience and quite understandable. The naming of the parameter's value is due to discussion, here it documents the implementation mechanism, which admittedly could be not the best solution fo a day to day usage.

But you say - WTF? You say - use Boost.Parameter! Why did I spend my time on those blogpost if there' a solution already? The reason is that in many project you either can't use it (company guidelines), or you wouldn't like to use it (already a big, do-it-all library in place). Another reason is that "small is beautiful"!

Tuesday, 13 May 2014

QString and QByteArray in VisualStudio 2013 Debugger.

Hi all!

Looking for a quick way to visualize Qt's classes in VS 2013? I was too! In my previous projects I used the Qt Add-In, and never thought about it - it was just there! But in the currentl project I don't feel like using the Add-In (several reasons, the main one is that it isn't pre-integrated in the development tols), so I looked for a simple visualizer for the VisualStudio's debugger. To my utter bewilderment, the solution didn't get disclosed in the first link of the Google query!!!??*

What should we do?  Real programmer would write an own visualizer, as described here and here. Or would they? Yes, you are right, he/she wouldn't, he/she would just try harder ;). And I was awarded a reward for my stubbornness: the code for a custom Qt visualizer for both Qt.4 and Qt.5 to be found here!

Unfortunately to the rest of you, the explanations are in russian, so you must try harder I guess ;). OK, don't despair, spending my childhood in a communist country finaly pays out ;) - here comes a short explanation how to create and install the visualizer.

1. Take this code and save it as (for example) qt4and5.natvis :
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">

 <!-- Qt 4 -->
    <Type Name="QString">
        <DisplayString>{d->data,su}</DisplayString>
        <StringView>d->data,su</StringView>
        <Expand>
            <Item Name="[size]">d-&gt;size</Item>
            <Item Name="[referenced]">d-&gt;ref._q_value</Item>
            <ArrayItems>
                <Size>d-&gt;size</Size>
                <ValuePointer>d->data,c</ValuePointer>
            </ArrayItems>
        </Expand>
    </Type>
 
    <Type Name="QByteArray">
        <DisplayString>{d->data,s}</DisplayString>
        <StringView>d->data,s</StringView>
        <Expand>
            <Item Name="[size]">d-&gt;size</Item>
            <Item Name="[referenced]">d-&gt;ref._q_value</Item>
            <ArrayItems>
                <Size>d-&gt;size</Size>
                <ValuePointer>d->data,c</ValuePointer>
            </ArrayItems>
        </Expand>
    </Type>
 
    <!-- Qt 5
    <Type Name="QString">
        <DisplayString>{((reinterpret_cast&lt;unsigned short*&gt;(d)) + d->offset / 2),sub}</DisplayString>
        <StringView>((reinterpret_cast&lt;unsigned short*&gt;(d)) + d->offset / 2),sub</StringView>
        <Expand>
            <Item Name="[size]">d-&gt;size</Item>
            <Item Name="[referenced]">d-&gt;ref.atomic._q_value</Item>
            <ArrayItems>
                <Size>d-&gt;size</Size>
                <ValuePointer>((reinterpret_cast&lt;unsigned short*&gt;(d)) + d->offset / 2),c</ValuePointer>
            </ArrayItems>
        </Expand>
    </Type>
 
    <Type Name="QByteArray">
        <DisplayString>{((reinterpret_cast&lt;char*&gt;(d)) + d-&gt;offset),sb}</DisplayString>
        <StringView>((reinterpret_cast&lt;char*&gt;(d)) + d-&gt;offset),sb</StringView>
        <Expand>
            <Item Name="[size]">d-&gt;size</Item>
            <Item Name="[referenced]">d-&gt;ref.atomic._q_value</Item>
            <ArrayItems>
                <Size>d-&gt;size</Size>
                <ValuePointer>((reinterpret_cast&lt;char*&gt;(d)) + d-&gt;offset),c</ValuePointer>
            </ArrayItems>
        </Expand>
    </Type>
    -->

</AutoVisualizer>
2. Copy this file to: C:\Users\Your_User_Name_Here\Documents\Visual Studio 2013\Visualizers

3. Restart VisualStudio!

That's all! After that, I'm able to see QString's and QByteArray's contents, and I hope you're able too! At the moment I'm still using Qt 4.8 for the current project, but the switch to Qt 5.2 is pending. When it arrives, I'll just uncomment the Qt.5 section in the file, and will be happy - or at least I hope so.

--
* OK, the solution for VS 2012 + Qt 5.2 does show up, but my constraints are somehow more generic than that.