basics

Quick Q: How to express constness of a forwarding reference?

Quick A: To express constness, a const reference is what is needed.

Recently on SO:

How to express constness of a forwarding reference?

How can I express that f does not modify its parameter?

If the function doesn't modify its parameter then there is no benefit to using a forwarding reference. You use a forwarding reference when you want to forward the parameter on to some other function which cares whether the argument is an lvalue or an rvalue (because maybe there are separate overloads for lvalues and rvalues, and the rvalue one can be more efficient).

If your function doesn't modify the argument then it shouldn't need to care whether it has an lvalue or rvalue, so it can just take const T& unconditionally. That can bind to both lvalues and rvalues, and promises not to modify the parameter.

template<typename T>
void f(const T& t) { ... }

Quick Q: Are `==` and `!=` mutually dependent?

Quick A: They are not, because it is not always true.

Recently on SO:

Are `==` and `!=` mutually dependent?

You would not want the language to automatically rewrite a != b as !(a == b) when a == b returns something other than a bool. And there are a few reasons why you might make it do that.

You may have expression builder objects, where a == b doesn't and isn't intended to perform any comparison, but simply builds some expression node representing a == b.

You may have lazy evaluation, where a == b doesn't and isn't intended to perform any comparison directly, but instead returns some kind of lazy<bool> that can be converted to bool implicitly or explicitly at some later time to actually perform the comparison. Possibly combined with the expression builder objects to allow complete expression optimisation before evaluation.

You may have some custom optional<T> template class, where given optional variables t and u, you want to allow t == u, but make it return optional<bool>.

There's probably more that I didn't think of. And even though in these examples the operation a == b and a != b do both make sense, still a != b isn't the same thing as !(a == b), so separate definitions are needed.

Typedef Literacy--Michael Park

typedef explained!

Typedef Literacy

by Michael Park

From the article:

The typedef declaration provides a way to create an alias for an existing type. For example, we can provide an alias for int called integer like so:

typedef int integer;

I imagine most people have seen such declarations, and they are fairly simple to read. In fact it’s so simple that we may incorrectly conclude that the syntax for typedef is:

typedef <existing_type> <new_type_name>;

Quick Q: was raw-pointer constructor of shared_ptr a mistake?

Quick A: No, its usage is well defined.

Recently on SO:

was raw-pointer constructor of shared_ptr a mistake?

In hindsight, given make_shared, would shared_ptr have a constructor that takes a raw pointer had it been introduced with C++11?
What if you don't control the allocation of the object? What if you need to use a custom deleter? What if you need list-initialization instead of parens?

None of these cases is handled by make_shared.

Additionally, if you're using weak_ptr, a shared_ptr allocated via make_shared won't free any memory until all the weak_ptrs are destroyed as well. So even if you have a normal shared pointer where none of the above apply, it's possible that you may still prefer the raw pointer constructor.

Yet another situation would be if your type provides overloads for operator new and operator delete. These may make it ill-suited for make_shared, since those overloads will not be called - and presumably they exist for a reason.

Quick Q: Why assigning a value is calling the implicit constructor?

Quick A: Because the default assignement operator knows only the type of your object, which it can get be calling the constructor.

Recently on SO:

What is the point of calling constructor with implicit conversion instead of assignment operator after an object is initalized?

There is no implicit CBox::operator=(double), so box = 2.0; has to create a temporary CBox object. It's equivalent to box = CBox(2.0);.

Making your constructor explicit disallows the implicit conversion from double to CBox, so no appropriate assignment operator exists, and you get a compile error.