Why do gcc and clang each produce different output for this program? (conversion operator vs constructor)

I believe clang’s result is correct.

In both bar_t a { foo } direct-list-initialization and in a static_cast between user defined types, constructors of the destination type are considered before user defined conversion operators on the source type (C++14 [dcl.init.list]/3 [expr.static.cast]/4). If overload resolution finds a suitable constructor then it’s used.

When doing overload resolution bar_t::bar_t<foo_t>(const foo_t&) is viable and will be a better match than one to any instantiation of this template resulting in the use of the cast operators on foo. It will also be better than any default declared constructors since they take something other than foo_t, so bar_t::bar_t<foo_t> is used.


The code as currently written depends on C++17 guaranteed copy elision; If you compile without C++17’s guaranteed copy elision (e.g. -std=c++14) then clang does reject this code due to the copy-initialization in bar_t b = static_cast<bar_t>(foo);.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)