[cfe-dev] C++11 error about initializing explicit constructor with {} ?

James Dennett james.dennett at gmail.com
Fri Jan 18 10:39:33 PST 2013


On Fri, Jan 18, 2013 at 8:32 AM, Benjamin Redelings
<benjamin.redelings at duke.edu> wrote:
> On 01/18/2013 05:01 AM, James Dennett wrote:
>>
>> On Fri, Jan 18, 2013 at 1:49 AM, Csaba Raduly <rcsaba at gmail.com> wrote:
>>>
>>> Hi Benjamin,
>>>
>>> On Thu, Jan 17, 2013 at 10:52 PM, Benjamin Redelings
>>> <benjamin.redelings at duke.edu> wrote:
>>>>
>>>> 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



More information about the cfe-dev mailing list