WTF C++
In this page, I enumerate various C++ fragments that sparkled my incomprehension when I encountered them, or made me scratch my head far too long. It is meant to be a reminder mainly for myself and destined to be updated over time.
No implicit conversion for arrays of 1 element
|
|
Filesystem library and operator /
Operator / does not always act relative to the previous path… A leading slash is always considered as referring to the root, therefore the input path is considered absolute instead of relative. Moral of the story: omit it or do not forget the leading dot!
|
|
Initialization of std::vector
|
|
Template template arguments, type or non-type argument headache
Template template arguments were made to enable templated classes/methods to depend on templated classes, for example imagine wanting to swap of hash map implementation. Unfortunately, a non-type template parameter and a type template parameter are not handled similarly by compilers and they cannot be mixed. Indeed, a pack typename...
will expect only type template argument, while auto...
will expect only non-type template arguments.
|
|
The above snippet leads to errors, while descriptive, can leave the user easily clueless: “type/value mismatch at argument N in template parameter list for…” for GCC, and “template template argument has different template parameters than its corresponding template template parameter” for Clang.
Trying to circumvent the problem by enforcing only 2 template parameters and leaving out the default parameters, which should be valid in C++17, will fail on Clang 10 unless the flag -frelaxed-template-template-args is provided or for clang on windows /clang:-frelaxed-template-template-args.
|
|
std::forward a lvalue reference leads to move
|
|
Factory functions (make_*
) and initializer lists
Compilers cannot deduce the final type of a brace-enclosed initializer lists from the delegated constructor.
|
|
error: no matching function for call to
make_unique<Foo>(<brace-enclosed initializer list>)
std::span
cannot be initialized from initializer lists
|
|
error: could not convert ‘{1, 2, 3}’ from ‘
’ to ‘std::span ’
But there is hope for C++26 with proposal P2447
Overload resolution between const&
and unconstrained template T&&
Due to overload resolution rules, the unconstrained template version will be preferred with a L-value std::string&
and R-value string&&
argument over the standard catch-all const&
. The forwarding reference would be resolved exactly for those argument type unlike the const reference variant, which is chosen later in the overload selection.
|
|