Why does {} as function argument not lead to ambiguity?

Max Langhof :

Consider this code:

#include <vector>
#include <iostream>

enum class A
{
  X, Y
};

struct Test
{
  Test(const std::vector<double>&, const std::vector<int>& = {}, A = A::X)
  { std::cout << "vector overload" << std::endl; }

  Test(const std::vector<double>&, int, A = A::X)
  { std::cout << "int overload" << std::endl; }
};

int main()
{
  std::vector<double> v;
  Test t1(v);
  Test t2(v, {}, A::X);
}

https://godbolt.org/z/Gc_w8i

This prints:

vector overload
int overload

Why does this not produce a compilation error due to ambiguous overload resolution? If the second constructor is removed, we get vector overload two times. How/by what metric is int an unambiguously better match for {} than std::vector<int>?

The constructor signature can surely be trimmed further, but I just got tricked by an equivalent piece of code and want to make sure nothing important is lost for this question.

StoryTeller - Unslander Monica :

It's in [over.ics.list], emphasis mine

6 Otherwise, if the parameter is a non-aggregate class X and overload resolution per [over.match.list] chooses a single best constructor C of X to perform the initialization of an object of type X from the argument initializer list:

  • If C is not an initializer-list constructor and the initializer list has a single element of type cv U, where U is X or a class derived from X, the implicit conversion sequence has Exact Match rank if U is X, or Conversion rank if U is derived from X.

  • Otherwise, the implicit conversion sequence is a user-defined conversion sequence with the second standard conversion sequence an identity conversion.

9 Otherwise, if the parameter type is not a class:

  • [...]

  • if the initializer list has no elements, the implicit conversion sequence is the identity conversion. [ Example:

    void f(int);
    f( { } ); // OK: identity conversion
    

    end example ]

The std::vector is initialized by constructor and the bullet in bold deems it a user defined converison. Meanwhile, for an int, this is the identity conversion, so it trumps the rank of the first c'tor.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=29324&siteId=1
Recommended