Articles & Books

Quick Q: Doesn't { } initialization guarantee no narrowing conversions? -- StackOverflow

Quick A: Yes, but some compilers have conforming extensions that give meaning to nonportable programs.

Preventing narrowing conversion when using std::initializer_list

#include <iostream>

struct X {
    X(std::initializer_list<int> list) { std::cout << "list" << std::endl; }
    X(float f) { std::cout << "float" << std::endl; }
};

int main() {
    int x { 1.0f };
    X a(1);     // float (implicit conversion)
    X b{1};     // list
    X c(1.0f);  // float
    X d{1.0f};  // list (narrowing conversion) ARG!!!

    // warning: narrowing conversion of '1.0e+0f' from 'float' to 'int'
    // inside { } [-Wnarrowing]
}

Is there any other way of removing std::initializer_list from an overload list (i.e., making the non-list ctors more favorable) instead of using the ()-initialization, or at least prohibiting narrowing conversion to happen (apart from turning warning into error)?

I was using http://coliru.stacked-crooked.com/ compiler which uses GCC 4.8.

 

Quick Q: Should I return a const value? -- StackOverflow

Quick A: No.

Some authors wrote "Consider doing this" in C++98. The answer is now a definite "No" because it prevents move from returned values.

Isn't the const modifier here unnecessary?

The "Effective C++" Item 3 says "Use const whenever possible", and it gives an example like:

 

const Rational operator*(const Rational& lhs,
                            const Rational& rhs);

to prevent clients from being able to commit atrocities like this:

Rational a, b, c;
...
(a * b) = c;   // invoke operator= on the result of a*b!

But isn't the non-reference return value of functions allready a rvalue? So why bother doing this?

GotW #90 Solution: Factories -- Herb Sutter

The solution to the latest GotW problem is now available:

GotW #90 Solution: Factories (updated for C++11/14)

by Herb Sutter

From the article:

Guideline: A factory that produces a reference type should return a unique_ptr by default, or a shared_ptr if ownership is to be shared with the factory.

Guideline: A factory that produces a non-reference type should return a value by default, and throw an exception if it fails to create the object. If not creating the object can be a normal result, return an optional<> value.

C++ auto and decltype Explained -- Thomas Becker

Here's a nice detailed treatment of auto and decltype by longtime author Thomas Becker.

C++ auto and decltype Explained

by Thomas Becker

From the article:

A while later, sometime in 2012, I noticed that there was another feature, or rather, a pair of features, in C++11 that I had not fully understood, namely, the auto and decltype keywords. With auto and decltype, unlike rvalue references, the problem is not that they are difficult to grasp. On the contrary, the problem is that the idea is deceptively easy, yet there are hidden subtleties that can trip you up.

Let's start with a good look at the auto keyword...

GotW #6b Solution: Const-Correctness, Part 2 -- Herb Sutter

The solution to GotW #6b is now available:

GotW #6b Solution: Const-Correctness, Part 2 (updated for C ++11/14)

by Herb Sutter

From the article:

Option 1 is to use a mutex in the perhaps-soon-to-be-canonical “mutable mutex mutables” pattern:

// Option 1: Use a mutex

    double get_area() const {
        auto lock = unique_lock<mutex>{mutables};
        if( area < 0 )   // if not yet calculated and cached
            calc_area();     // calculate now
        return area;
    }

private:
    // ...
    mutable mutex  mutables;      // canonical pattern: mutex that
    mutable double area;          //   covers all mutable members

Option 1 generalizes well if you add more data members in the future. However, it’s also more invasive and generalizes less well if you add more const member functions in the future that use area, because they will all have to remember to acquire a lock on the mutex before using area.

Option 2 is to just change double to mutable atomic<double>. ...