May 2016

Folds(ish) in C++11

Folds of variadic expressions are coming in C++17, but what about today?

Folds(ish) in C++11

by Jason Turner

From the article:

It is possible to perform some form of the variadic folds that are coming in C++17 with the C++11 and C++14 compilers that we have available today by using just a little bit of creativity.

...

Someone (not me) figured out that we can abuse the std::initializer_list type to let us guarantee the order of execution of some statements while not having to recursively instantiate templates. For this to work we need to create some temporary object to let us use the braced initializer syntax and hold some result values for us.

Only problem is, our print function doesn’t return a result value. So what do we do? Give it a dummy return value!

#include <iostream>

template<typename T>
void print(const T &t)
{
  std::cout << t << '\n';
}

template<typename ... T>
  void print(const T& ... t)
{
  std::initializer_list<int>{ (print(t), 0)... };
}

int main()
{
  print(1, 2, 3.4, "Hello World");
}

...

(And we continue to simplify it much more from here...)

Quick Q: std::rethrow_exception and thrown exception type

Quick A: std::make_exception_ptr creates a reference on a copy.

Recently on SO:

std::rethrow_exception and thrown exception type

From documentation for std::make_exception_ptr:

Creates an std::exception_ptr that holds a reference to a copy of e.

Unfortunately, copying e means you get object slicing (which @Mohamad Elghawi points out is also more prominently mentioned later on that page). When you call std::make_exception_ptr<RecognitionException>, it will hold a copy of a RecognitionException, not any derived class.

But you don't need exception_ptr at all here. Even though reportError does not have the try...catch in scope, you can still use throw; to re-throw the current exception.

#include <stdio.h>

struct A { virtual ~A() = default; };
struct B : A { };

void reportError() {
  try {
    throw;
  }
  catch (B &) {
    puts("caught B");
  }
  catch (A &) {
    puts("caught A");
  }
}

int main() {
  try {
    throw B();
  }
  catch (A &) {
    reportError();
  }
}

Quick Q: Static constexpr int vs old-fashioned enum: when and why?

Quick A: A static constexpr cannot be used in an ODR context.

Recently on SO:

Static constexpr int vs old-fashioned enum: when and why?

There will be no noticeable difference for integral constants when used like this.

However, enum is actually better, because it is a true named constant. constexpr integral constant is an object which can be, for example, ODR-used - and that would result in linking errors.

#include <iostream>

struct T {
    static constexpr int i = 42;
    enum : int {x = 42};
};

void check(const int& z) {
    std::cout << "Check: " << z << "\n";
}

int main() {
    // check(T::i); // Uncommenting this will lead to link error
    check(T::x);
}

When check(T::i) is uncommented, the program can not be linked:

/tmp/ccZoETx7.o: In function `main': ccc.cpp:(.text+0x45): undefined reference to `T::i' collect2: error: ld returned 1 exit status

However, the true enum always works.

Diagnosable validity -- Andrzej KrzemieĊ„ski

Andrzej Krzemieński wrote down his thoughts on ill-formed C++ code.


Diagnosable validity

by Andrzej Krzemieński

From the article:

Certain combinations of types and expressions can make a C++ program ill-formed. “Ill-formed” is a term taken from the C++ Standard and it means that a program is not valid, and compiler must (in most of the cases) reject it. This is quite obvious:

int main()
{
  auto i = "some text".size(); // invalid expression
};

String literals do not have member functions, therefore compiler cannot accept this program, and must report an error. This puts a responsibility on programmers to learn which expressions and types are valid in a given context and use only these. Again, I am saying a very obvious thing.

What is less obvious is that there is a way in C++ to enter a type or expression of which we do not know if it is valid or not, in an isolated environment, where it does not render the entire program ill-formed, but instead it returns a yes-no (or rather valid-invalid) answer, which we can use at compile-time to make a decision how we want the program to behave. When requested, compiler can analyze all the declarations it has seen so far, and make an approximated judgement whether a given type or expression would make the program ill-formed or not, if used outside the isolated environment. The compiler’s approximated answer is not always correct, but it is just enough most of the time.

 

ACCU 2016 All videos are online

All videos from the this year's ACCU conference are now online.

ACCU 2016 Videos

by the ACCU

From the schedule

The keynotes were:

Jim Coplien: A Glimpse of Trygve: From Class oriented Programming to Real OO

Andrei Alexandrescu: Fastware

Marian Petre: Balacing Bias in Software Development

Anna-Jayne Metcalfe: Comfort Zone

 

The talks with C++ content in no particular order were:

Dietmar Kühl: Constant Fun

Roger Orr: C++ Concepts 'Lite' in Practice

Felix Petriconi: Leaving The Dark Side - Behaviour Testing of a C++ Based Medical Device

J. Daniel Garcia: Improving Performance and Maintainability in Modern C++

Marshall Clow: STL Algorithms – How to Use Them and How to Write Your Own

Kevlin Henney: Declarative Thinking, Declarative Practice

Dmitri Nesteruk: Design Pattern in Modern C++

Jamie Allsop: Managing C++ Build Complexity Using Cuppa: A SCons-based Build System

Nikos Athanasiou: Benchmarking in C++

Sławomir Zborowski: What Every C++ Programmer Should Know About Modern Compilers

Peter Sommerlad: Visualize Template Instantiations - Understand your Template Bugs

Peter Sommerlad: Using Units, Quantities, and Dimensions in C++14

Niall Douglas: Distributed Mutual Exclusion using Proposed Boost.AFIO

John Lakos: Proper Inheritance Part 1 (Part 2 is not available)

Bernhard Merkle: Finding Bugs with Clang at Compile and Run Time

Guy Davidson: WG21-SG14: The Story So Far

 

Quick Q: Templated Function results in Circular Inclusion

Quick A: Separate definition and implementation.

Recently on SO:

Templated Function results in Circular Inclusion

Define registerEvent after IApp.

class IApp;

class Component
{
    IApp* app;
    template<typename T>
    void registerEvent(const int& evtId, Status (T::*func) (int));
};

class IApp : public Component {
  ...
};

template <typename T>
Component::registerEvent(const int& evtId, Status (T::*func) (int)) {
  auto res = std::bind(func, (T*)this, std::placeholders::_1);
  app->registerForEvent(evtId);
}

If need be, also define A::registerEvent after Component::registerEvent.

Quick Q: Why is list initialization (using curly braces) better than the alternatives?

Quick A: It is less likely to generate an unexpected error.

Recently on SO:

Why is list initialization (using curly braces) better than the alternatives?

Basically copying and pasting from Bjarne Stroustrup's "The C++ Programming Language 4th Edition":

List initialization does not allow narrowing (§iso.8.5.4). That is:

  • An integer cannot be converted to another integer that cannot hold its value. For example, char to int is allowed, but not int to char.
  • A floating-point value cannot be converted to another floating-point type that cannot hold its value. For example, float to double is allowed, but not double to float.
  • A floating-point value cannot be converted to an integer type.
  • An integer value cannot be converted to a floating-point type.

Example:

void fun(double val, int val2) {

    int x2 = val; // if val==7.9, x2 becomes 7 (bad)

    char c2 = val2; // if val2==1025, c2 becomes 1 (bad)

    int x3 {val}; // error: possible truncation (good)

    char c3 {val2}; // error: possible narrowing (good)

    char c4 {24}; // OK: 24 can be represented exactly as a char (good)

    char c5 {264}; // error (assuming 8-bit chars): 264 cannot be
                   // represented as a char (good)

    int x4 {2.0}; // error: no double to int value conversion (good)

}

The only situation where = is preferred over {} is when using auto keyword to get the type determined by the initializer.

Example:

auto z1 {99}; // z1 is an initializer_list<int>
auto z2 = 99; // z2 is an int

Conclusion

Prefer {} initialization over alternatives unless you have a strong reason not to.

CppCon 2015 Expression Templates - Past, Present, Future--Joel Falcou

Have you registered for CppCon 2016 in September? Don’t delay – Early Bird registration is open now.

While we wait for this year’s event, we’re featuring videos of some of the 100+ talks from CppCon 2015 for you to enjoy. Here is today’s feature:

Expression Templates - Past, Present, Future+

by Joel Falcou

Part 1: (watch on YouTube) (watch on Channel 9)

Part 2: (watch on YouTube) (watch on Channel 9)

Part 3: (watch on YouTube) (watch on Channel 9)

Summary of the talk:

Expression Templates is one of this C++ idiom people learn to either love or hate. The main issues with ET is that everubody has its own conception about what they are, when they should be used, what benefits they give and what are their trade off. For a long time, Expression Tempaltes has been seen has a way to improve temporary heavy code. If the seminal implementation of ET by Todd Veldhuizen was actually about this, the landscape has changed since C++11 and C++14.

This workshop will go over : - what are exactly Expression Templates and what kind of use case they can solve elegantly and efficiently - what are the benefits that one may reap by using expression tempalte in its library - what are the real cost of expressont empaltes both at runtime and compile-time - which tools to use to not reinvent the tempalte wheel everytime including an introduction to Boost.PROTO an Boost.HANA.

The main objective is to clarify why, even in C++1*, this idiom has a meaningful set of applications and how to navigate around its pitfalls.