C++11 error about initializing explicit constructor with {} ?

Hi,

     I'm trying to compile some of my C++11 code under clang-3.2; I originally wrote it under g++. This is a case where g++-4.8 (snapshot) accepts my code, but clang-3.2 does not. The error message is:

In file included from ../../../master/src/mcmc/moves.C:20:
In file included from ../../../master/src/mcmc/sample.H:26:
../../../master/src/mcmc/mcmc.H:390:94: error: chosen constructor is explicit in copy-initialization
     std::set<int> get_affected_parameters(const owned_ptr<Probability_Model>&) const {return {};}
^~
/usr/include/c++/v1/set:378:14: note: constructor declared here
     explicit set(const value_compare& __comp = value_compare())

So, basically, this code is trying to initialize a std::set<int> with {}. I'm not sure clang is right here, but I'm also not sure is wrong. Can someone tell me, so I can possibly submit a bug report?

-BenRI

Hi Benjamin,

Hi,

    I'm trying to compile some of my C++11 code under clang-3.2; I
originally wrote it under g++. This is a case where g++-4.8 (snapshot)
accepts my code, but clang-3.2 does not. The error message is:

In file included from ../../../master/src/mcmc/moves.C:20:
In file included from ../../../master/src/mcmc/sample.H:26:
../../../master/src/mcmc/mcmc.H:390:94: error: chosen constructor is
explicit in copy-initialization
    std::set<int> get_affected_parameters(const
owned_ptr<Probability_Model>&) const {return {};}
^~
/usr/include/c++/v1/set:378:14: note: constructor declared here
    explicit set(const value_compare& __comp = value_compare())

So, basically, this code is trying to initialize a std::set<int> with {}.
I'm not sure clang is right here, but I'm also not sure is wrong. Can
someone tell me, so I can possibly submit a bug report?

Maybe it's already fixed. The following code:

#include <set>
std::set<int> getset() { return {}; }

is compiled without errors by

$ clang++ -v --std=c++0x setinit.cc
clang version 3.3 (trunk 172707)
Target: x86_64-unknown-linux-gnu
Thread model: posix

Csaba

You may be compiling against libstdc++, which has a C++11-compliance
bug in that its default constructor for set is not explicit (while the
standard specifies that it should be), which would make this compile
when it should not.

(On the other hand, I'm not sure that the standard _meant_ to specify
that, or if it was just an accident. Turning {} into an empty set
seems like a rather pretty thing.)

-- James

I don't think the issue is the standard library, and I'm not sure its fixed in clang 3.3. I checked these combinations:

clang, libstdc++: yes
clang, libstdc++ modified to reflect the standard: NO
clang, libc++: NO

gcc, libstdc++: yes
gcc, libstdc++ modified to reflect the standard: yes.

Here "modifed to reflect the standard" means removing the constructor set::set(), and adding a default argument to the constructor
explicit set(const _Compare& __comp, const allocator_type& __a = allocator_type())
     to yield
explicit set(const _Compare& __comp=_Compare(), const allocator_type& __a = allocator_type())

So, it seems that libstdc++ is indeed wrong, but g++ accepts {} even when libstdc++ is fixed.

On the other hand, clang accepts {}, but only with the non-standard compliant libstdc++.

-BenRI

Hi Benjamin,

Hi,

     I'm trying to compile some of my C++11 code under clang-3.2; I
originally wrote it under g++. This is a case where g++-4.8 (snapshot)
accepts my code, but clang-3.2 does not. The error message is:

In file included from ../../../master/src/mcmc/moves.C:20:
In file included from ../../../master/src/mcmc/sample.H:26:
../../../master/src/mcmc/mcmc.H:390:94: error: chosen constructor is
explicit in copy-initialization
     std::set<int> get_affected_parameters(const
owned_ptr<Probability_Model>&) const {return {};}
^~
/usr/include/c++/v1/set:378:14: note: constructor declared here
     explicit set(const value_compare& __comp = value_compare())

So, basically, this code is trying to initialize a std::set<int> with
{}.
I'm not sure clang is right here, but I'm also not sure is wrong. Can
someone tell me, so I can possibly submit a bug report?

Maybe it's already fixed. The following code:

#include <set>
std::set<int> getset() { return {}; }

is compiled without errors by

$ clang++ -v --std=c++0x setinit.cc
clang version 3.3 (trunk 172707)
Target: x86_64-unknown-linux-gnu
Thread model: posix

You may be compiling against libstdc++, which has a C++11-compliance
bug in that its default constructor for set is not explicit (while the
standard specifies that it should be), which would make this compile
when it should not.

(On the other hand, I'm not sure that the standard _meant_ to specify
that, or if it was just an accident. Turning {} into an empty set
seems like a rather pretty thing.)

-- James

I don't think the issue is the standard library, and I'm not sure its fixed
in clang 3.3. I checked these combinations:

clang, libstdc++: yes
clang, libstdc++ modified to reflect the standard: NO
clang, libc++: NO

Thanks for running these tests. The results above are consistent with
Clang being correct...

gcc, libstdc++: yes
gcc, libstdc++ modified to reflect the standard: yes.

...and GCC being buggy.

Here "modifed to reflect the standard" means removing the constructor
set::set(), and adding a default argument to the constructor
explicit set(const _Compare& __comp, const allocator_type& __a =
allocator_type())
    to yield
explicit set(const _Compare& __comp=_Compare(), const allocator_type& __a =
allocator_type())

So, it seems that libstdc++ is indeed wrong, but g++ accepts {} even when
libstdc++ is fixed.

Right; libstdc++ and GCC are both buggy.

On the other hand, clang accepts {}, but only with the non-standard
compliant libstdc++.

Clang's behavior is correct, I believe. Do you have reason to suppose not?

-- James

I reported the libc++ / libstdc++ part of this as a defect a few months ago:

http://cplusplus.github.com/LWG/lwg-active.html#2193