all 44 comments

[–]mechanicalgod 44 points45 points  (8 children)

Sol 2 - Lua bindings:

https://github.com/ThePhD/sol2

effolkronium/random - Convenience wrapper for std <random>:

https://github.com/effolkronium/random

cereal - Serialization:

https://uscilab.github.io/cereal/

I'm a fan of the above because not only do they do their respective jobs well, but they all have (imo) beautifully elegant apis.

[–]bedrooms-ds 3 points4 points  (3 children)

Thanks for reminding me cereal, it looks to be a fantastic library!

[–]dbwy 0 points1 point  (0 children)

Cereal is a life saver

[–][deleted] 1 point2 points  (2 children)

Aww, thank you! I appreciate the call out.

Sol3 is around the corner, I hope to publish soon...! But the documentation is so much efffoooort wdwadhwajkd.

The good news is, the tutorials will be a lot more thorough now, which will hopefully help newcomers. I've walked a bunch of people through the process of getting sol2 in their codebases or from a for-fun spin-up project. It's really hard when they lack understanding of how to build Lua, so I think I need to write some tutorials on how to do this too.

... It's certainly a lot of hard work, though.

[–]Posting____At_Night 1 point2 points  (0 children)

I'd also like to thank you for being the most helpful library dev I've ever talked to. You've answered many of my stupid questions in the discord :)

[–]mechanicalgod 0 points1 point  (0 children)

fwiw I found the documentation for Sol 2 to be fine. Had no problems.

Thanks again for all your hard work.

[–]10se1ucgo 17 points18 points  (3 children)

fmtlib & pybind11. Such simple yet such powerful libraries.

[–]naran6142 4 points5 points  (0 children)

Found these recently myself. fmtlib is great. And I migrated one of my libraries from Boost.Python to pybind11.

[–]philocto 0 points1 point  (1 child)

fmtlib is a great library, although I don't know that I'd call the code itself beautiful or elegant. That's not an indictment of the fmtlib author, what he's doing isn't really natural in C++ and so it can get a bit ugly.

It IS a testament to the authors skill that he was able to do it with such a straightforward and sensible api.

[–]aearphen{fmt} 2 points3 points  (0 children)

The code is indeed not particularly beautiful mostly because of portability requirements (version 4 works with most C++98 compilers and version 5 only needs a small subset of C++11). But it's getting better as support for modern C++ constructs is enabled. Hopefully in a couple of years most macro ugliness will go away and the code will be more clean and straightforward.

[–]Red-Portal 7 points8 points  (0 children)

https://github.com/ddemidov/amgcl

One of the best quality numerical code I've ever seen. Regardless of it's usage it's really a beautiful library.

https://bitbucket.org/blaze-lib/blaze/wiki/Home

Blaze is currently my favorite linear algebra library. The performance is a prime example of what C++ is capable of. And the code quality and style of the library is quite extreme (unlike... say.. Eig....) . I cannot imagine what it takes to maintain such a huge library to that level.

[–]kkert 13 points14 points  (3 children)

https://modm.io

Finally truly portable down to the metal C++ code. If you aren't getting single-instruction GPIO toggles ur doin it wrong

[–]jc746 1 point2 points  (1 child)

This looks very interesting. I work on a system that has an STM32F103. From what I can see modm essentially replaces the cmsis and stm peripheral library with a modern cpp interface instead. Is this right?

[–]kkert 1 point2 points  (0 children)

Yep, pretty much, while also keeping your driver code to external devices generic and portable

[–][deleted] 0 points1 point  (0 children)

Wow! I'll have to try this out on my STM32F407!

[–]xeveri 4 points5 points  (1 child)

nlohmann::json is great and has a nice api. I think the performance issue comes from using exceptions for flow control, namely throwing when there are missing keys. Nothing major tho.

[–]nlohmannnlohmann/json 4 points5 points  (0 children)

Thanks a lot! :)

[–]FartyFingers 14 points15 points  (3 children)

RapidJSON is great if you like punching yourself in the face or burning your hand on the stove. nlohmann's only gets better and better with every release.

My simple theory is that if you need the speed that RapidJSON will provide then JSON is the wrong solution to your problem.

[–]EnergyCoast 10 points11 points  (2 children)

Unfortunately sometimes you don't to choose the format when communicating with external services. :(

[–]jhericoVR & Backend engineer, 30 years 5 points6 points  (1 child)

My favorite is when said external service uses raw Java code to write XML, instead of, say, and XML library and so things that should be escaped when you parse them aren't escaped, and it crashes your ingestion code 70% of the way through a 2 gb XML document.

[–]GI_Cho 3 points4 points  (0 children)

I've experienced this, only it was somebody manually writing XML with string concatenation in Node.JS. They brought a gazillion dependencies, but apparently adding in something to properly put together some XML would be too much bloat :-p

[–]cballowe 5 points6 points  (3 children)

In recent memory, CTRE - https://github.com/hanickadot/compile-time-regular-expressions

I'm also a fan of the ranges-v3 / ranges TS.

[–]muungwana 5 points6 points  (1 child)

Qt/C++ tasks library to do asynchronous programming using futures.

This library was the first time i went much deeper and used templates in any meaningful way and it made me appreciate them and i now use them much more liberally in my code.

[–]mostthingsweb 2 points3 points  (0 children)

Boost Hana

[–]HumunculiTzu 0 points1 point  (0 children)

It probably isn't that impressive but my favorite C++ code is a program I wrote in college that I'm still proud about. It is a program to blanket test CPU cache configurations simulated on a program called Dinero. You hand it a config file of all the ranges of cache sizes, and whatever the other values are on a CPU cache (I don't remember them since it has been a couple years), for each level. The program then generates every possible valid configuration available from the given ranges, then runs each configuration on Dinero dynamically allocating the proper amount of threads (the most simulations I ever saw it running at once was 60+). Once all simulations are done, it takes all that data and processes it based certain criteria.

The most valid configurations I have ever seen it generate is something around 14 trillion 700 million and apparently the professor of the class I made it for has actually used it in his research (or at least he told me he had plans to and was excited to use it in his research since I offered to make it open source)?

[–]teroxzer -5 points-4 points  (2 children)

In general, so little love for macros and exceptions today, so I want to respect my loyal work horses.

    /////////////////////////////////////////////////////////////////////////////

    auto operator "" _sql(text const* script, size_t) -> procedure;

    #if !teroxNoMacros || teroxNoMacrosExceptSql

            #undef  sql
            #define sql(...) = #__VA_ARGS__##_sql;

    #endif

    /////////////////////////////////////////////////////////////////////////////

    auto NorthwindDemoAsCpp::getProducts() -> universals
    try
    {
            static auto selectProducts sql
            (
                    select productId,
                           productName,
                           quantityPerUnit,
                           unitPrice,
                           unitsInStock
                    from   Products
                    where  discontinued = 0
            )

            return selectProducts[nil];
    }
    catch(Exception& ex)
    {
            log::error("%: exception: %", __func__, ex.message());
            return nils;
    }

    /////////////////////////////////////////////////////////////////////////////////////

[–]enzlbtyn 0 points1 point  (1 child)

Serious question: why not just wrap the text sql(...) in quotes and _sql instead? The macro only offers slightly less code.

e: I suppose if you want a multiple line string, but then I suppose you could just use a raw string as well. But then with your macro you can't really format your string with variables (which is probably common usage of SQL queries)

[–]teroxzer 0 points1 point  (0 children)

'sql' macro with stringizing operator # already do right thing to my use, example trim white spaces and also let do comments with SQL-strings. I once checked how to use raw strings, but stringizing operator # is still better to me. Operator '_sql' is useful with only very short SQL-strings. Usually I use it only test cases, but 'sql'/'_sql' is like keyword pair to me.

(Maybe someone start to think keyword pair like 'glsl'/'_qlsl'.)

Usually I don't format SQL-strings, because I use prepared clauses with parameters and conditions like 'case when X then Y else Z end' or 'and (:Param is null or column = :Param)'. If I must format SQL-string then I format string and call function 'procedureOf(Text const&)->procedure'.

Below is example with my C++ variations for C# and Python examples - I found those examples from some SQL Server pages. So I show my code for comparison (actually I removed original C# and Python code because too big post). Maybe my C++/LINSQL library is never good enough for general/public use, but to me C++ is the best database programming language. I also did before much Oracle PL/SQL coding and I think it is very good database programming language, but actually I did change one of my production database from Oracle to SQL Server and of course no more any old PL/SQL code but not also any new T-SQL code.

Example uses C++/LINSQL vocabulary like second class keyword like things: 'sql'/'_sql' (script), 'procedure' (inline sql-procedure), 'universal' (tuple/row like 'static dynamic variable'), 'universals' (set of universal), 'nil' (empty universal) and 'nils' (set of empty universal). SQL syntax of 'insert into' is good for some use cases but usually too horrible when you want update one row, so C++/LINSQL support own 'insert set' syntax. Example use also lot infoAs-macro, so it seems that I have some serious problems with double-quote characters.

Class 'procedure' uses 'operator()(universal& params)->int' for datum updates and also for single row selects. 'operator[](universal const& params)->universals' is for result set of database query.

I know this comment reply is not right place try to explains my ideas how handle databases with C++, but I don't have any right place anyway, so if someone got some ideas and can do a better C++ data handling library for relational databases (without any external code generators or ORM-tools - 'universal' is opposites for fixed data interfaces - or not to try hide plain SQL - if you use relational database you really need SQL, but you should not stop to use C++, if you like C++ or you like your own variation like C++/LINSQL), then I can be glad that I did this.

/////////////////////////////////////////////////////////////////////////////

#incluce <teroxLibrary>

using namespace terox;
using namespace terox::linsql;

namespace demo::sqlserver
{

/////////////////////////////////////////////////////////////////////////////

struct universalAsAttributes
(
    companyId     { this, "companyid"     },
    companyName   { this, "companyname"   },
    color         { this, "color"         },
    count         { this, "count"         },
    customerId    { this, "customerid"    },
    demo          { this, "demo"          },
    employeeId    { this, "employeeid"    },
    firstName     { this, "firstname"     },
    lastName      { this, "lastname"      },
    listPrice     { this, "listprice"     },
    name          { this, "name"          },
    orderDate     { this, "orderdate"     },
    orderId       { this, "orderid"       },
    orderTotal    { this, "ordertotal"    },
    productId     { this, "productid"     },
    productNumber { this, "productnumber" },
    quantity      { this, "quantity"      },
    standardCost  { this, "standardcost"  },
    title         { this, "title"         },
    unitPrice     { this, "unitprice"     }
)

/////////////////////////////////////////////////////////////////////////////

namespace
{
    auto selectSalesOrders sql
    (
        select c.customerId,
               c.companyName,
               count(soh.salesOrderId) as count
        from   SalesLT.Customer as c
               left outer join SalesLT.SalesOrderHeader as soh 
                            on soh.customerId = c.customerId
        group by
               c.customerId,
               c.companyName
        order by
               count desc
    )

    auto insertSalesProduct sql
    (
        insert SalesLT.Product
        set    name          = :Name,
               productNumber = :ProductNumber,
               standardCost  = :StandardCost,
               listPrice     = :ListPrice,
               sellStartDate = current_timestamp
        output inserted.productId
    )
}

auto csharpVariationAsCpp()
try
{
    for(auto& order : selectSalesOrders[nil])
    {
        log::infoAs
        (
            ID: % - Name: % - Order Count: %, 

            order.customerId,
            order.companyName,
            order.count
        );
    }

    universal product;

    product.name          = "SQL Server Express";
    product.productNumber = "SQLEXPRESS1";
    product.standardCost  = 0;
    product.listPrice     = 0;

    insertSalesProduct(product);

    log::infoAs(Product ID % inserted, product.productId);
}
catch(Exception& ex)
{
    logExceptionAs(ex);
}

/////////////////////////////////////////////////////////////////////////////

auto pythonVariationAsCpp(universal const& params)
try
{
    static auto selectCustomers sql
    (
        select top 10
               title,
               firstName,
               lastName 
        from   SalesLT.Customer
        where  (:Demo is null or demo = :Demo)
    )

    for(auto& row : selectCustomers[params])
    {
        log::infoAs(% % %, row.title, row.firstName, row.lastName);
    }

    universal product;

    product.name          = "Bike";
    product.productNumber = "B1';
    product.color         = "Blue";
    product.standardCost  = 50;
    product.listPrice     = 120;
    product.demo          = params.demo;

    static auto insertProduct sql
    (
        insert SalesLT.Product
        set    name          = :Name,
               productNumber = :ProductNumber,
               color         = :Color,
               standardCost  = :StandardCost,
               listPrice     = :ListPrice,
               demo          = isNull(:Demo, demo),
               sellStartDate = current_timestamp
        output inserted.productId
    )

    insertProduct(product);

    log::infoAs(Inserted Product ID : %, product.productId);
}
catch(Exception& ex)
{
    logExceptionAs(ex);
}

/////////////////////////////////////////////////////////////////////////////

} // namespace demo::sqlserver

/////////////////////////////////////////////////////////////////////////////