|
Boost : |
Subject: Re: [boost] Updated boost::base_from_member for C++2011
From: Daryle Walker (darylew_at_[hidden])
Date: 2012-02-15 23:19:46
> From: darylew_at_[hidden]
> Date: Tue, 14 Feb 2012 11:08:10 -0500
>
>
> > Date: Sun, 12 Feb 2012 17:15:37 +0100
> > From: vicente.botet_at_[hidden]
> >
> > there are some problems with clang-3.0 c++0x
> >
> > clang-darwin.compile.c++
> > ../../../bin.v2/libs/test/build/clang-darwin-3.0x/debug/link-static/threading-multi/unit_test_parameters.o
> > In file included from ../../../libs/test/src/unit_test_parameters.cpp:16:
> > In file included from ../../../boost/test/impl/unit_test_parameters.ipp:32:
> > In file included from
> > ../../../boost/test/utils/runtime/cla/dual_name_parameter.hpp:21:
> > In file included from
> > ../../../boost/test/utils/runtime/cla/named_parameter.hpp:21:
> > In file included from
> > ../../../boost/test/utils/runtime/cla/basic_parameter.hpp:27:
> > ../../../boost/utility/base_from_member.hpp:75:66: error: no matching
> > constructor for initialization of 'boost::runtime::cla::string_name_policy'
> > BOOST_NOEXCEPT_IF( BOOST_NOEXCEPT_EXPR(::new ((void*) 0)
> > MemberType(
> > ^
> > ../../../boost/config/suffix.hpp:648:53: note: expanded from:
> > # define BOOST_NOEXCEPT_EXPR(Expression) noexcept((Expression))
> > ^
> > ../../../boost/config/suffix.hpp:647:50: note: expanded from:
> > # define BOOST_NOEXCEPT_IF(Predicate) noexcept((Predicate))
> > ^
> > ../../../boost/utility/base_from_member.hpp:74:30: note: in
> > instantiation of function template specialization
> > 'boost::base_from_member<boost::runtime::cla::string_name_policy,
> > 0>::base_from_member<const
> > boost::base_from_member<boost::runtime::cla::string_name_policy, 0> &>'
> > requested here
> > explicit BOOST_CONSTEXPR base_from_member( T&& ...x )
> > ^
> > ../../../boost/test/utils/runtime/cla/named_parameter.hpp:34:7: note:
> > candidate constructor (the implicit copy constructor) not viable: no
> > known conversion from 'const
> > boost::base_from_member<boost::runtime::cla::string_name_policy, 0>' to
> > 'const boost::runtime::cla::string_name_policy' for 1st argument;
> > class string_name_policy : public basic_naming_policy {
> > ^
> > ../../../boost/test/utils/runtime/cla/named_parameter.hpp:37:5: note:
> > candidate constructor not viable: requires 0 arguments, but 1 was provided
> > string_name_policy();
> > ^
> >
>
> Any ideas for a fix? Does there need to be explicitly declared copy (and move) constructors?
I asked about this on StackOverflow, and we've discovered a new C++ gotcha. If we have a universal constructor:
struct MyType{ template <typename ...Args> MyType( Args&& ...x );};
Matches every kind of argument except two:
* anything with "volatile"* a "const &&"
Since we have an explicitly declared constructor, the automatically defined default constructor is cancelled. That's OK since this constructor template will serve as it. The compiler will also search for constructor profiles that can act as the copy- and move-constructor, ignoring all constructor templates, even if they could match. Since there's no explicitly declared non-template constructors, MyType gains two:
* MyType( MyType const & ) = default;* MyType( MyType && ) = default;
Although constructor templates are ignored when determining if the automatic copy/move-constructors are made, they are NOT ignored when overload resolution needs to be done! If you're copying from a non-const object, the universal constructor will match a "MyType &" before the copy constructor's "MyType const &" would! This is what's causing the conflict.
The way around it is to add an "unused" EnableIf template parameter to the constructor template that cancels the template when Args is a single argument and the argument's type is MyType.
I'll work that in.
Daryle W.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk