[bug?] list-initialization failures in a return statement

I've found what I think are a couple of bugs in how clang (3.4) list-initializes objects in a return statement. It probably applies to any copy-list-initialization context, but I haven't tested all the possibilities. I'm posting this here instead of just filing a bug because I wanted to get some feedback on whether I'm correct about this or not.

OK, but value-initialization defers to default-initialization here, and
default-initialization performs overload resolution to select the default
constructor. This -- presumably -- uses to select the constructor:

"When objects of non-aggregate class type T are list-initialized (8.5.4),
overload resolution selects the constructor in two phases:
-- [choose from initializer-list constructors]
-- [try all constructors]
If the initializer list has no elements and T has a default constructor,
the first phase is omitted. In copy-list-initialization, if an explicit
constructor is chosen, the initialization is ill-formed."

Since we're in copy-list-initialization, T has a default constructor, and
the list has no elements, we try all constructors. Since we pick an
explicit constructor, the program is ill-formed.

Hmm. Does this mean it's impossible to write a function that constructs an arbitrary DefaultConstructible object? I had hoped to do something like

   template<typename T>
   T make() {
     return {};

so that I could construct non-movable objects, but I guess that won't work for objects with explicit default constructors. It seems like clang is indeed doing the right thing, so perhaps this is an issue to bring up with the standards committee...

- Jim

If you'll excuse me making up terms, DefaultConstructible only requires
that direct-default-initialization is valid, not that
copy-default-list-initialization is valid. That's probably the bug in the
standard; your type should probably not be considered to be

Here's a dumb workaround:

  template<typename T> struct DirectInit {
    T value{};
    operator T&() & { return value; }
    operator T&&() && { return value; }
    // ...
  template<typename T> DirectInit<T> make() { return {}; }

... but I'm somewhat wondering why you would have an explicit default
constructor in the first place.

Well, in practice, *I'd* never want it, but I was trying to be as generic as possible, since this is part of a factory function for a test framework, and I'm not in control of the types in question.

Really, this is more of a curiosity for me at the moment, since I'm ok with saying "objects with explicit default-ctors can't be used as a test fixture" (and if I ever change my mind, I can easily write a specialization of the relevant code to avoid this). Still, it's a bit disheartening that the standard still has this edge-case in what I'd argue is a part of "perfect forwarding".

I'll write up a message about this and post it to the ISO discussion group just for the sake of completeness. Maybe it'll turn out to be an issue someone else has an interest in, but if not, I'm not terribly upset.

Anyway, thanks for the references to the relevant part of the standard.

- Jim