I encountered some situation that I cannot explain.
I succeeded to reproduce the problem in a short example:
My class MyObj (originally nlohmann::json) has 2 constructors: move constructor and constructor that receives std::initializer_list.
gcc compiler always prefers the constructor with std::initializer_list while clang prefers move constructor.
The example can be reproduced in online compiler: http://coliru.stacked-crooked.com/
The compilation line: g++ -std=c++14 -O0 -pthread main.cpp && ./a.out
clang++ -std=c++14 -O0 -pthread main.cpp && ./a.out
#include <iostream>#include <initializer_list>template <class T>class MyUnion{public: MyUnion(T&& t): _t{std::move(t)} {} T _t;};struct MyObj{ MyObj() : _a(0) { std::cout << "ctor"<< std::endl; } MyObj(MyObj&& r) : _a(std::move(r._a)) { std::cout << "m.ctor"<< std::endl; } MyObj(const MyObj&& r) : _a(std::move(r._a)) { std::cout << "cm.ctor"<< std::endl; } MyObj(const MyObj& r) : _a(r._a) { std::cout << "c.ctor"<< std::endl; } MyObj(std::initializer_list<MyObj> l) : _a(0) { std::cout << "ctr(list)"<< std::endl; } ~MyObj() { std::cout << "~dtor"<< std::endl; } int _a;};int main(){ std::cout << "MyObj"<< std::endl; MyObj a{MyObj{}}; std::cout << "\nMyUnion"<< std::endl; MyUnion<MyObj> u1{MyObj{}}; std::cout << "\nfinish"<< std::endl; return 0;}
gcc output:
MyObjctorctr(list)~dtorMyUnionctorm.ctorctr(list)~dtor~dtorfinish~dtor~dtor
clang output:
MyObjctorMyUnionctorm.ctor~dtorfinish~dtor~dtor