Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

what are the overload resolution rules of list-initialization

there are some codes here

#include <iostream>
struct A {
    A(int) {}
};
struct B {
    B(A) {
        std::cout<<"0"<<std::endl;
    }
    B(B const&) {
        std::cout << "1" << std::endl;
    }
    B(B&&) {
        std::cout << "2" << std::endl;
    }
};
int main() {
    B b0{{0}}; // this is ok  #1
    B b( {0} ); //this is error #2
}

g++ report:

main.cpp: In function ‘int main()’:
main.cpp:17:11: error: call of overloaded ‘B(<brace-enclosed initializer list>)’ is ambiguous
  B b({ 0 });
           ^
main.cpp:12:2: note: candidate: B::B(B&&)
  B(B&&) {
  ^
main.cpp:9:2: note: candidate: B::B(const B&)
  B(B const&) {
  ^
main.cpp:6:2: note: candidate: B::B(A)
  B(A) {

clang report:

main.cpp:17:4: error: call to constructor of 'B' is ambiguous
        B b({ 0 });
          ^ ~~~~~
main.cpp:6:2: note: candidate constructor
        B(A) {
        ^
main.cpp:12:2: note: candidate constructor
        B(B&&) {
        ^
main.cpp:9:2: note: candidate constructor
        B(B const&) {
        ^
1 error generated.

{0} will convert to temporary object A and the contructor B(A) will be selected, #1 and #2 are all the "direct-constructor" form ,why #1 is ok ,#2 has three candidate constructor and is ambiguous?

like image 737
xmh0511 Avatar asked Nov 19 '19 09:11

xmh0511


People also ask

What is overload resolution?

The process of selecting the most appropriate overloaded function or operator is called overload resolution. Suppose that f is an overloaded function name. When you call the overloaded function f() , the compiler creates a set of candidate functions.

What are overloaded functions in C++?

C++ lets you specify more than one function of the same name in the same scope. These functions are called overloaded functions, or overloads. Overloaded functions enable you to supply different semantics for a function, depending on the types and number of its arguments.

How do you initialize a list in CPP?

In C++11 and above, we can use the initializer lists '{...}' to initialize a list. This won't work in C++98 as standard permits list to be initialized by the constructor, not by '{...}' .

What is function overloading?

An overloaded function is really just a set of different functions that happen to have the same name. The determination of which function to use for a particular call is resolved at compile time. In Java, function overloading is also known as compile-time polymorphism and static polymorphism.


Video Answer


1 Answers

Because for #1, the copy and move constructors are disallowed by [over.best.ics]/4 (emphasized mine):

However, if the target is

  • the first parameter of a constructor or
  • the implicit object parameter of a user-defined conversion function

and the constructor or user-defined conversion function is a candidate by

  • [over.match.ctor], when the argument is the temporary in the second step of a class copy-initialization,

  • [over.match.copy], [over.match.conv], or [over.match.ref] (in all cases), or

  • the second phase of [over.match.list] when the initializer list has exactly one element that is itself an initializer list, and the target is the first parameter of a constructor of class X, and the conversion is to X or reference to cv X,

user-defined conversion sequences are not considered. [ Note: These rules prevent more than one user-defined conversion from being applied during overload resolution, thereby avoiding infinite recursion.  — end note ]

So it is the language rule that distinguishes ({...}) and {{...}}. Note the ({...}) case falls into [over.match.ctor] but the argument is NOT the temporary in the second step of a class copy-initialization, so the first bullet does not apply.

You can further read Issue 2076 to see it is intended to disallow the copy and move constructors for the inner brace in the {{...}} case:

The resolution of issue 1467 made some plausible constructs ill-formed. For example,

struct A { A(int); };
struct B { B(A); };
B b{{0}};

This is now ambiguous, because the text disallowing user-defined conversions for B's copy and move constructors was removed from 16.3.3.1 [over.best.ics] paragraph 4...

like image 80
xskxzr Avatar answered Oct 26 '22 00:10

xskxzr