Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Avoid accidentally creating a temporary

Reply
Thread Tools

Avoid accidentally creating a temporary

 
 
Phil Endecott
Guest
Posts: n/a
 
      05-15-2011
Dear Experts,

Say I have this:

struct scoped_foo {
scoped_foo(int n) { enable_foo(n); }
~scoped_foo() { disable_foo(); }
};

and I use it like this:

{
scoped_foo(3);
blah(); // foo is enabled here
}
// foo is disabled here

....except that doesn't work, because I should have written

{
scoped_foo ANY_NAME_HERE(3);
....

I've now made this mistake a few times, and it's annoying.

So, my question: is there anything that I can do in my declaration of
scoped_foo so that trying to use it in this wrong way, i.e. to create
a temporary rather than an object with scope up to the next }, will
give an error, or at least a warning (with g++)?

Thanks for any suggestions!

Phil.
 
Reply With Quote
 
 
 
 
Howard Hinnant
Guest
Posts: n/a
 
      05-15-2011
On May 15, 12:15*pm, Phil Endecott <(E-Mail Removed)> wrote:
> Dear Experts,
>
> Say I have this:
>
> struct scoped_foo {
> * scoped_foo(int n) { enable_foo(n); }
> * ~scoped_foo() { disable_foo(); }
>
> };
>
> and I use it like this:
>
> {
> * scoped_foo(3);
> * blah(); *// foo is enabled here}
>
> // foo is disabled here
>
> ...except that doesn't work, because I should have written
>
> {
> * scoped_foo ANY_NAME_HERE(3);
> * ....
>
> I've now made this mistake a few times, and it's annoying.
>
> So, my question: is there anything that I can do in my declaration of
> scoped_foo so that trying to use it in this wrong way, i.e. to create
> a temporary rather than an object with scope up to the next }, will
> give an error, or at least a warning (with g++)?


This would be a great use for lvalue-ref qualifiers on destructors:

~scoped_foo()& { disable_foo(); }

Unfortunately this use of reference qualifiers is disallowed.

Perhaps you could propose it.

Disclaimer: This is off the cuff. I haven't fully investigated such
proposed use.

Howard
 
Reply With Quote
 
 
 
 
Johannes Schaub
Guest
Posts: n/a
 
      05-15-2011
Howard Hinnant wrote:

> On May 15, 12:15 pm, Phil Endecott <(E-Mail Removed)> wrote:
>> Dear Experts,
>>
>> Say I have this:
>>
>> struct scoped_foo {
>> scoped_foo(int n) { enable_foo(n); }
>> ~scoped_foo() { disable_foo(); }
>>
>> };
>>
>> and I use it like this:
>>
>> {
>> scoped_foo(3);
>> blah(); // foo is enabled here}
>>
>> // foo is disabled here
>>
>> ...except that doesn't work, because I should have written
>>
>> {
>> scoped_foo ANY_NAME_HERE(3);
>> ....
>>
>> I've now made this mistake a few times, and it's annoying.
>>
>> So, my question: is there anything that I can do in my declaration of
>> scoped_foo so that trying to use it in this wrong way, i.e. to create
>> a temporary rather than an object with scope up to the next }, will
>> give an error, or at least a warning (with g++)?

>
> This would be a great use for lvalue-ref qualifiers on destructors:
>
> ~scoped_foo()& { disable_foo(); }
>
> Unfortunately this use of reference qualifiers is disallowed.
>


We discussed it in #llvm before and Doug found it's an interesting idea.
Also see http://stackoverflow.com/questions/4...t-possible-to-
restrict-class-instances-to-be-used-only-as-temporaries for another guy
desperately looking for something like this, but in the opposite direction
("&&" instead of "&")

 
Reply With Quote
 
Öö Tiib
Guest
Posts: n/a
 
      05-15-2011
On May 15, 7:15*pm, Phil Endecott <(E-Mail Removed)> wrote:
> Dear Experts,
>
> Say I have this:
>
> struct scoped_foo {
> * scoped_foo(int n) { enable_foo(n); }
> * ~scoped_foo() { disable_foo(); }
>
> };
>
> and I use it like this:
>
> {
> * scoped_foo(3);
> * blah(); *// foo is enabled here}
>
> // foo is disabled here
>
> ...except that doesn't work, because I should have written
>
> {
> * scoped_foo ANY_NAME_HERE(3);
> * ....
>
> I've now made this mistake a few times, and it's annoying.
>
> So, my question: is there anything that I can do in my declaration of
> scoped_foo so that trying to use it in this wrong way, i.e. to create
> a temporary rather than an object with scope up to the next }, will
> give an error, or at least a warning (with g++)?
>
> Thanks for any suggestions!


Stop using magic numbers.

#include "your_scoped_foo.h"

const int kaka = 3;

int main()
{
* scoped_foo(kaka); // no default constructor for scoped_foo
}


 
Reply With Quote
 
Alf P. Steinbach /Usenet
Guest
Posts: n/a
 
      05-15-2011
* Phil Endecott, on 15.05.2011 18:15:
> Dear Experts,
>
> Say I have this:
>
> struct scoped_foo {
> scoped_foo(int n) { enable_foo(n); }
> ~scoped_foo() { disable_foo(); }
> };
>
> and I use it like this:
>
> {
> scoped_foo(3);
> blah(); // foo is enabled here
> }
> // foo is disabled here
>
> ...except that doesn't work, because I should have written
>
> {
> scoped_foo ANY_NAME_HERE(3);
> ....
>
> I've now made this mistake a few times, and it's annoying.
>
> So, my question: is there anything that I can do in my declaration of
> scoped_foo so that trying to use it in this wrong way, i.e. to create
> a temporary rather than an object with scope up to the next }, will
> give an error, or at least a warning (with g++)?
>
> Thanks for any suggestions!


How about


<code>
#include <stdio.h>
#include <assert.h>

void enable_foo( int ) { printf( "e\n" ); }
void disable_foo() { printf( "d\n" ); }

namespace detail
{
struct scoped_foo_impl
{
scoped_foo_impl( scoped_foo_impl const& )
{
assert( "Ouch, copy constructing! Probably no RVO..." );
}

explicit scoped_foo_impl( int n )
{
enable_foo( n );
}

~scoped_foo_impl() { disable_foo(); }
};

scoped_foo_impl make_foo( int n ) { return scoped_foo_impl( n ); }
}

typedef detail::scoped_foo_impl const& scoped_foo;
using detail::make_foo;

int main()
{
scoped_foo g = make_foo( 3 );
//scoped_foo make_foo( 3 ); // Nix!
//scoped_foo( 3 ); // Nyet!

printf( "*\n" );
}
</code>


Cheers & hth.,


- Alf "why didn't they ask me"

--
blog at <url: http://alfps.wordpress.com>
 
Reply With Quote
 
Alf P. Steinbach /Usenet
Guest
Posts: n/a
 
      05-15-2011
* Alf P. Steinbach /Usenet, on 15.05.2011 19:50:
> * Phil Endecott, on 15.05.2011 18:15:
>> Dear Experts,
>>
>> Say I have this:
>>
>> struct scoped_foo {
>> scoped_foo(int n) { enable_foo(n); }
>> ~scoped_foo() { disable_foo(); }
>> };
>>
>> and I use it like this:
>>
>> {
>> scoped_foo(3);
>> blah(); // foo is enabled here
>> }
>> // foo is disabled here
>>
>> ...except that doesn't work, because I should have written
>>
>> {
>> scoped_foo ANY_NAME_HERE(3);
>> ....
>>
>> I've now made this mistake a few times, and it's annoying.
>>
>> So, my question: is there anything that I can do in my declaration of
>> scoped_foo so that trying to use it in this wrong way, i.e. to create
>> a temporary rather than an object with scope up to the next }, will
>> give an error, or at least a warning (with g++)?
>>
>> Thanks for any suggestions!

>
> How about
>
>
> <code>
> #include <stdio.h>
> #include <assert.h>
>
> void enable_foo( int ) { printf( "e\n" ); }
> void disable_foo() { printf( "d\n" ); }
>
> namespace detail
> {
> struct scoped_foo_impl
> {
> scoped_foo_impl( scoped_foo_impl const& )
> {
> assert( "Ouch, copy constructing! Probably no RVO..." );
> }
>
> explicit scoped_foo_impl( int n )
> {
> enable_foo( n );
> }
>
> ~scoped_foo_impl() { disable_foo(); }
> };
>
> scoped_foo_impl make_foo( int n ) { return scoped_foo_impl( n ); }
> }
>
> typedef detail::scoped_foo_impl const& scoped_foo;
> using detail::make_foo;
>
> int main()
> {
> scoped_foo g = make_foo( 3 );
> //scoped_foo make_foo( 3 ); // Nix!
> //scoped_foo( 3 ); // Nyet!
>
> printf( "*\n" );
> }
> </code>
>
>
> Cheers & hth.,
>
>
> - Alf "why didn't they ask me"
>


oh, forgot an "&& false" or other such device in the assert. just add


--
blog at <url: http://alfps.wordpress.com>
 
Reply With Quote
 
Phil Endecott
Guest
Posts: n/a
 
      05-15-2011
On May 15, 5:15 pm, Phil Endecott <(E-Mail Removed)> wrote:
> struct scoped_foo {
> scoped_foo(int n) { enable_foo(n); }
> ~scoped_foo() { disable_foo(); }
> };


> is there anything that I can do in my declaration of
> scoped_foo so that trying to use it in this wrong way, i.e. to create
> a temporary rather than an object with scope up to the next }, will
> give an error, or at least a warning (with g++)?


I guess I want something like this:

scoped_foo(int n) __attribute__((warn_unused_result))
{ enable_foo(n); }

which doesn't work, but perhaps there's something similar that I can
do.

BTW, one case where this could really hurt is scoped locks:

{
Lock(mutex); // Nope. But I could stare at it for hours and not
spot the error.
modify(shared_state); // Ooops. Hard to debug that.
}


Phil.
 
Reply With Quote
 
Alf P. Steinbach /Usenet
Guest
Posts: n/a
 
      05-15-2011
* Phil Endecott, on 15.05.2011 20:33:
> On May 15, 5:15 pm, Phil Endecott<(E-Mail Removed)> wrote:
>> struct scoped_foo {
>> scoped_foo(int n) { enable_foo(n); }
>> ~scoped_foo() { disable_foo(); }
>> };

>
>> is there anything that I can do in my declaration of
>> scoped_foo so that trying to use it in this wrong way, i.e. to create
>> a temporary rather than an object with scope up to the next }, will
>> give an error, or at least a warning (with g++)?

>
> I guess I want something like this:
>
> scoped_foo(int n) __attribute__((warn_unused_result))
> { enable_foo(n); }
>
> which doesn't work, but perhaps there's something similar that I can
> do.
>
> BTW, one case where this could really hurt is scoped locks:
>
> {
> Lock(mutex); // Nope. But I could stare at it for hours and not
> spot the error.
> modify(shared_state); // Ooops. Hard to debug that.
> }


Why are you replying to your own post?

Anyway, see my reply.

And also, you might want to look up the ScopeGuard article by Marginean and
Alexandrescu in DDJ.


Cheers & hth.,

- Alf "baffled"

--
blog at <url: http://alfps.wordpress.com>
 
Reply With Quote
 
Johannes Schaub
Guest
Posts: n/a
 
      05-15-2011
Alf P. Steinbach /Usenet wrote:

> * Phil Endecott, on 15.05.2011 18:15:
>> Dear Experts,
>>
>> Say I have this:
>>
>> struct scoped_foo {
>> scoped_foo(int n) { enable_foo(n); }
>> ~scoped_foo() { disable_foo(); }
>> };
>>
>> and I use it like this:
>>
>> {
>> scoped_foo(3);
>> blah(); // foo is enabled here
>> }
>> // foo is disabled here
>>
>> ...except that doesn't work, because I should have written
>>
>> {
>> scoped_foo ANY_NAME_HERE(3);
>> ....
>>
>> I've now made this mistake a few times, and it's annoying.
>>
>> So, my question: is there anything that I can do in my declaration of
>> scoped_foo so that trying to use it in this wrong way, i.e. to create
>> a temporary rather than an object with scope up to the next }, will
>> give an error, or at least a warning (with g++)?
>>
>> Thanks for any suggestions!

>
> How about
>
>
> <code>
> #include <stdio.h>
> #include <assert.h>
>
> void enable_foo( int ) { printf( "e\n" ); }
> void disable_foo() { printf( "d\n" ); }
>
> namespace detail
> {
> struct scoped_foo_impl
> {
> scoped_foo_impl( scoped_foo_impl const& )
> {
> assert( "Ouch, copy constructing! Probably no RVO..." );
> }
>
> explicit scoped_foo_impl( int n )
> {
> enable_foo( n );
> }
>
> ~scoped_foo_impl() { disable_foo(); }
> };
>
> scoped_foo_impl make_foo( int n ) { return scoped_foo_impl( n );
> }
> }
>
> typedef detail::scoped_foo_impl const& scoped_foo;
> using detail::make_foo;
>
> int main()
> {
> scoped_foo g = make_foo( 3 );
> //scoped_foo make_foo( 3 ); // Nix!
> //scoped_foo( 3 ); // Nyet!
>
> printf( "*\n" );
> }
> </code>
>
>


This is a neat trick, I will have to remember it. Sadly, it doesn't work
with list initialization

scoped_foo make_foo{ 3 }; // valid
scoped_foo { 3 }; // valid


 
Reply With Quote
 
Alf P. Steinbach /Usenet
Guest
Posts: n/a
 
      05-15-2011
* Johannes Schaub, on 15.05.2011 20:49:
> Alf P. Steinbach /Usenet wrote:
>
>> * Phil Endecott, on 15.05.2011 18:15:
>>> Dear Experts,
>>>
>>> Say I have this:
>>>
>>> struct scoped_foo {
>>> scoped_foo(int n) { enable_foo(n); }
>>> ~scoped_foo() { disable_foo(); }
>>> };
>>>
>>> and I use it like this:
>>>
>>> {
>>> scoped_foo(3);
>>> blah(); // foo is enabled here
>>> }
>>> // foo is disabled here
>>>
>>> ...except that doesn't work, because I should have written
>>>
>>> {
>>> scoped_foo ANY_NAME_HERE(3);
>>> ....
>>>
>>> I've now made this mistake a few times, and it's annoying.
>>>
>>> So, my question: is there anything that I can do in my declaration of
>>> scoped_foo so that trying to use it in this wrong way, i.e. to create
>>> a temporary rather than an object with scope up to the next }, will
>>> give an error, or at least a warning (with g++)?
>>>
>>> Thanks for any suggestions!

>>
>> How about
>>
>>
>> <code>
>> #include<stdio.h>
>> #include<assert.h>
>>
>> void enable_foo( int ) { printf( "e\n" ); }
>> void disable_foo() { printf( "d\n" ); }
>>
>> namespace detail
>> {
>> struct scoped_foo_impl
>> {
>> scoped_foo_impl( scoped_foo_impl const& )
>> {
>> assert( "Ouch, copy constructing! Probably no RVO..." );
>> }
>>
>> explicit scoped_foo_impl( int n )
>> {
>> enable_foo( n );
>> }
>>
>> ~scoped_foo_impl() { disable_foo(); }
>> };
>>
>> scoped_foo_impl make_foo( int n ) { return scoped_foo_impl( n );
>> }
>> }
>>
>> typedef detail::scoped_foo_impl const& scoped_foo;
>> using detail::make_foo;
>>
>> int main()
>> {
>> scoped_foo g = make_foo( 3 );
>> //scoped_foo make_foo( 3 ); // Nix!
>> //scoped_foo( 3 ); // Nyet!
>>
>> printf( "*\n" );
>> }
>> </code>
>>
>>

>
> This is a neat trick, I will have to remember it. Sadly, it doesn't work
> with list initialization
>
> scoped_foo make_foo{ 3 }; // valid
> scoped_foo { 3 }; // valid
>
>


C++0x is off-topic...

Cheers,

- Alf

--
blog at <url: http://alfps.wordpress.com>
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Accidentally Deleted a Folder in Outlook Express amanda.wolkenhauer@gmail.com Computer Support 6 12-15-2007 05:38 PM
How to protect the LCD from being scratched accidentally? dalimoh@gmail.com Digital Photography 41 03-30-2007 07:58 AM
! "My documents" folder accidentally overwritten Rock Gibbons Computer Support 21 03-26-2007 11:39 PM
I Want To Retrieve Files On A 20D CF Card That I Accidentally Formatted Clyde Torres Digital Photography 3 10-22-2004 02:25 AM
Are there any free utilities to recover an accidentally deleted photo from a SmartMedia card? sm9 © Digital Photography 12 08-14-2003 11:27 AM



Advertisments