> On 25 Aug 2014, at 12:48,
sai...@gmail.com wrote:
> I would like to float an idea which I have been thinking on since I learned the details of noexcept. I believe turning the const qualifier into a compile time conditional as with noexcept ( defaulting to true ) could finally allow us to fold a lot of code duplication for geters in particular.
I quite like the idea of const optinally becoming a compile-time conditional similar to noexcept! In the past I have discussed with people the idea of "constness templates" using something like the snippet below (first in the LWG at the Berlin meeting where the feedback was roughly along the lines "now he has lost it completely"; since then I managed to get better feedback, e.g., at a BSI meeting earlier this year):
template <const cv>
auto& foo::get_bar() cv { return this->m_bar; }
One stumbling block why I haven't pursued that direction is that somewhat requires quite a bit machinary to compute the qualifiers. This need is neatly avoided by making const (and, of course, volatile) conditional on a constant expression. The notation using constness templates is somewhat nicer which could lead to something like
template <bool is_const>
auto& foo::get_bar() const(is_const) { return this->m_bar; }
if the argument of the const can be deduced: unlike the property of whether a function throws an exception, the constness of the object pointed to by this is a known property of an argument. Making this property deducible doesn't look like too much of a stretch.
> As stated, the greatest win as I see it would be to reduce code duplication for geters using the following technique:
>
> struct foo
> {
> // If const could deduce true / false from the constness of an argument this would obviously get a lot less akward
> auto& get_bar() const( std::is_const< typename std::remove_pointer< decltype( this ) >::type >::value )
Of course, even if the argument can't be deduced, the declaration could be simplified to
auto& get_bar() const(is_const<decltype(*this)>)
Using something like:
template <typename T>
constexpr bool is_const = std::is_const<typename std::remove_reference<T>::type>::value;
Since the constness property of the object is likely to be used in multiple places, I'd think it would be desirable to deduce the constness and give it a name in this process. I can also imagine that compiler implementers are not too keen on evaluating arbitrary expressions in the argument of const while determining an overload set (on the other hand, noexcept already requires this anyway).
> begin() / end() for iterators which decides constness from parameter could be written as ( if constness could be deduced from parameter ):
>
> auto begin() const( *this ) -> iterator < value_type const( *this ) >
When following the lead of noexept the qualifier and the expression would be separate, though:
auto begin() const(const(*this)) -> iterator<value_type const(const(*this))>
Since constness of a type can already be determine without much effort, e.g., using variable templates I'm not sure if the a const-testing operator is really needed. This is different for the conditional const qualifier which cannot be emulated for member functions.
One thing worth considering is whether the optional expression could lead to ambiguities. There is no issue for the const/volatile qualifiers of member functions. When conditional const/volatile qualifiers are used for arguments in a function declaration, I could image interaction with existing rules.
In summary:
1. I'm definitely in favor of a mechanism making const and volatile qualifiers optionally conditional on a boolean constexr.
2. A const-testing operator isn't really essential but it would probably be prudent to include in an initial proposal, ideally in a disentangled way making it easy to remove it if necessary.
3. It may be reasonable to provide supporting library components.