Consider following binary tree, where nodes have two sons or are leafs with labels. This code compiles in g++ 4.7.2:
#include <memory>
using namespace std;
struct Tree {
unique_ptr<Tree> left, right;
char label;
Tree(char label) : label(label) {}
Tree(Tree && left, Tree && right) :
left(new Tree(move(left))),
right(new Tree(move(right))) {}
//~ explicit Tree(Tree && left, bool right) {}
} tree {{1, 2}, 3};
When I uncomment explicit constructor it fails to compile (if this explicit constructor is private it fails too). Is this gcc bug, or explicit constructors forbid using initializer list construction for non-explicit ones with same number of arguments?
Edit: s/implicit/non-explicit/. Sorry for confusion, I used word “implicit” for “allowing implicit conversion” and “explicit” as “marked with the keyword explicit”. I call constructors automagically generated by compiler “default”, so I didn’t notice word “implicit” will be so ambiguous.
Your question seems to assume something which is not true, and reveals a fundamental misunderstanding.
To begin with, implicitly generated constructors are not hidden “when using initializer lists”. Their generation is simply inhibited any time you define a constructor, no matter whether you mark it as
explicitor not.Beware though: what is usually meant by “implicit” constructor is a constructor which is implicitly (automatically) generated by the compiler when you provide none, not a constructor which lacks the
explicitmodifier. In the above paragraph I was talking about the former, but I am led to believe that you are thinking about the latter.Assuming that this is the case, it is not true that constructors which are not marked as
explicitare hidden by ones that are marked asexplicitin general, whether or not you are using initializer lists.The reason your program does not compile is that your
explicitconstructor happens to be a better match than the non-explicitone, because it accepts aboolas its second argument, which only requires a standard conversion to match the argument2. On the other hand, your non-explicitconstructor accepting aTree&&requires a user-defined conversion involving the construction of a temporaryTreeobject, and standard conversions are preferable over user-defined conversions.To force the compiler to construct a
Treetemporary from the argument2rather than converting2to abool(and, therefore, invoke the non-explicitconstructor), you must specify this by changing your constructor invocation into the following:Also notice, that while the same applies to the creation of the top-level tree (i.e.
3gets converted into aboolas well and yourexplicitconstructor is invoked again), this is not a problem in this case, because you are direct-initializing thetreeobject, and no implicit conversion is attempted.