Sometimes it's desirable to use const methods on a non-const object.This can be done with const_cast, but const_cast can equally well be used to do potentially unsafe things and is often flagged up in code reviews or banned outright by coding standards/pre-commit scripts.
implicit_cast is nice for situations like this, if you have it— static_cast can still do unwelcome things if you're not careful. Speaking of which, we ought to standardize implicit_cast.
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
implicit_cast is nice for situations like this, if you have it— static_cast can still do unwelcome things if you're not careful. Speaking of which, we ought to standardize implicit_cast.
Sometimes it's desirable to use const methods on a non-const object.
--
std::string getWordForm(const Sentence& sent, Sentence::size_type abs_pos, Sentence::difference_type shift)
{
std::string form;
auto pos = as_signed(abs_pos) + shift;
if (pos >= 0 && as_unsigned(pos) < sent.size()) form = sent[as_unsigned(pos)].form();
return form;
}>as_signed sounds like a recipe for overflowNo more than any other signed arithmetic.A typical example of use:
// Make sure that this multiplication is unsigned so that when it overflows,
// it is well-defined as wrapping around.
template <typename X>
X wrap_square(X x)
{
return static_cast<X>(as_unsigned(x) * as_unsigned(x));
}
Sometimes it's desirable to use const methods on a non-const object.This can be done with const_cast, but const_cast can equally well be used to do potentially unsafe things and is often flagged up in code reviews or banned outright by coding standards/pre-commit scripts.
On Monday, August 18, 2014 1:11:26 AM UTC-7, vadim.pet...@gmail.com wrote:>as_signed sounds like a recipe for overflow
No more than any other signed arithmetic.A typical example of use:
These are very problematic. Let's say you wrote code like this:
// Make sure that this multiplication is unsigned so that when it overflows,
// it is well-defined as wrapping around.
template <typename X>
X wrap_square(X x)
{
return static_cast<X>(as_unsigned(x) * as_unsigned(x));
}
...except that this is wrong: it has undefined behavior on 32-bit machines when X is std::uint16_t. Despite the attempt at doing unsigned arithmetic, it still is doing signed arithmetic. Worse yet, this is platform-specific.
I share your skepticism, and am still waiting for a motivating code example of where as_const is needed.
On Mon, Aug 18, 2014 at 11:12 PM, Andrew Tomazos <andrew...@gmail.com> wrote:I share your skepticism, and am still waiting for a motivating code example of where as_const is needed.for (x : as_const(v))
{// got x from begin const / end const}
struct Foo
{T& foo()
{
// maybe more useful with as_non_const?return const_cast<T&>(as_const(*this).foo());}T const& foo() const
{
// ...
}};
On Monday, August 18, 2014 8:12:57 PM UTC-7, Andrew Tomazos wrote:On Tue, Aug 19, 2014 at 4:58 AM, Greg Marr <greg...@gmail.com> wrote:
What am I missing here? You can already use const methods on non-const objects without a cast. Are you trying to select a const overload in favor of a non-const overload?I share your skepticism, and am still waiting for a motivating code example of where as_const is needed.
Linked list iterators can be more complicated if they have to account for the possibility of list elements being deleted during the current iteration.
Exactly. I'm not saying it is necessarily a good idea, but I believe it would address the undefined behavior in the above test case.
for (x : as_const(v))
{// got x from begin const / end const}
I think this is better:for (const auto& x : v) { ... }But STL also has this in the works:for (const x : v) { ... }
Also, if v is a temporary, will your version be lifetime extended?
boost::adaptors::reversed |
boost::adaptors::uniqued | vecNobody said it does.
It looks to me like a design flaw in Boost. The adaptors are not designed to
compose, yet the syntax they chose allows well-formed expressions that fail
That's news to me.
The as_const problem at hand is easily solved by overloading the factory
function on rvalues, using return by value.
That will not help with the lifetime issue.
It's news to me that those adaptors are not designed to compose, yes.
Sure it does, see the demo. as_const works with lvalues and rvalues alike.The as_const problem at hand is easily solved by overloading the factoryThat will not help with the lifetime issue.
function on rvalues, using return by value.
No it doesn't, if you combine as_const with other expressions, as EWG 120
illustrates. The subexpression temporaries are gone by the time the loop is
entered, even if the temporary in the full expression gets a lifetime extension.
Whether that's worth fixing is another matter.
struct Foo
{T& foo()
{
// maybe more useful with as_non_const?return const_cast<T&>(as_const(*this).foo());}T const& foo() const
{
// ...
}};
On Sat, Aug 16, 2014 at 1:05 PM, Jonathan Coe <jonath...@gmail.com> wrote:
Sometimes it's desirable to use const methods on a non-const object.
For example?
It looks to me like a design flaw in Boost. The adaptors are not designed to compose, yet the syntax they chose allows well-formed expressions that fail at runtime.
It would have been safer if they’d put the adaptors on the LHS:boost::adaptors::reversed | boost::adaptors::uniqued | vec