Clang ne peut pas utiliser l’initialisation contreventée pour la conversion définie par l’utilisateur

Le code suit.

struct A { A() {} }; struct B { B() {} explicit operator A() { return A{}; } }; struct C { A a; C(B b) : a{b} {} }; 

J’ai un struct A qui n’est pas constructible par agrégat (car il a un constructeur défini). Il en va de même pour la struct B Mais il a aussi un opérateur de conversion explicite défini par l’utilisateur à struct A Maintenant, le constructeur de la struct C prend une struct B et l’utilise pour construire la struct A Comme dans cppreference , l’opérateur de conversion peut participer à l’initialisation directe, ce qui est le cas pour l’initialisation par le membre de la struct C Il passe sur GCC 5.2 (C ++ 11). Mais cependant, il échoue sur Clang 3.6. J’ai essayé avec C ++ 11, C ++ 14 et C ++ 1z.

Si je change de a{b} en a(b) , il passe à la fois sur Clang et sur GCC.

Je me demande si c’est un bug de Clang ou si j’ai mal compris la norme?

Un changement récent de clang en raison du DR1467 (cfr. 22259 )

Les versions récentes de gcc et de clang agissent correctement: comstackz votre code sans erreurs.

Lors du premier cycle de résolution de surcharge pour la liste d’initialisation de membres, les constructeurs A sont ignorés car ils ne sont pas des constructeurs de liste d’initialiseurs.

Ensuite [over.match.list] / p1 prend la relève

  • Si aucun constructeur de liste d’initialiseurs viable n’est trouvé, la résolution de surcharge est effectuée à nouveau, les fonctions candidates correspondant à tous les constructeurs de la classe T et la liste d’arguments étant constituée des éléments de la liste d’initialiseurs.

et cette fois, les constructeurs de A sont pris en compte. Les constructeurs copier et déplacer de A ont suffisamment d’arguments pour correspondre au processus de résolution de surcharge et ils ne provoquent aucune suppression de conversion définie par l’utilisateur, car 13.3.1.3 et même 13.3.1.7 (toujours dans le code de Clang ) ne s’appliquent pas à ces constructeurs.

Par conséquent, ils sont entrés dans l’ensemble de résolution de surcharge et [over.best.ics] s’applique.