Return link to temporary

I understand that it’s illegal to return a link to a temporary one, but here is my problem:

const stringSet & Target::dirList( const dirType type ) const { switch( type ) { case SOURCE_DIR: return m_sourceDirs; case HEADER_DIR: return m_headerDirs; case RESOURCE_DIR: return m_resourceDirs; default: return stringSet(); // PROBLEM HERE! } } 

The first three three parameters return a constant reference to the stringSet data stringSet . What to do for the default case? If I leave it, the compiler (GCC with -Wall -Wextra -pedantic ) complains, and I don’t want this, because these parameters tend to catch my bed design options in the most unusual ways :)

Thanks!

+4
source share
6 answers

Keep the default value as a member too ... and return a link to it. This, of course, is theoretically possible by default. If this is not the case, throw an exception and return nothing.

 default: throw invalid_argument_exception(); 
+9
source
 const stringSet & Target::dirList( const dirType type ) const { static const stringSet defaultSet; // <-- switch( type ) { case SOURCE_DIR: return m_sourceDirs; case HEADER_DIR: return m_headerDirs; case RESOURCE_DIR: return m_resourceDirs; default: return defaultSet; // <-- } } 
+4
source

You cannot return a link to a temporary object created on the stack. I will be destroyed by the time your function returns, and your application will crash.

If you are going to do something like this, you will have to return by value, not by reference, i.e.

stringSet Target::dirList( const dirType type ) const

This, obviously, can have performance implications, as you will most likely end up with a copy creator called for your other links. An alternative would be to avoid creating a temporary object on the stack. Depending on your application, there are several ways to do this, for example, to have a simple pool from which you get your temporary objects, which are collected at some point in the garbage, or you could use dirList for the stringSet argument, which is filled in according to your functions.

Best case - don't you just have a constant default? Do I need to be unique for every call?

0
source

Not always the right option, but for what you can use shared_ptr for this - build shared_ptr with a zero deleter and return that if the rowset already exists, otherwise create one that points to the empty row and has a normal deleter and return it. In other words:

 #include <set> #include <string> #include <boost/shared_ptr.hpp> struct NullDeleter { void operator()(void *p) {} }; enum DirType { SOURCE_DIR, HEADER_DIR, RESOURCE_DIR, OTHER, }; typedef std::set<std::string> StringSet; typedef boost::shared_ptr<const StringSet> StringSet_CPtr; struct Target { StringSet m_sourceDirs, m_headerDirs, m_resourceDirs; Target() { m_sourceDirs.insert("/source"); m_headerDirs.insert("/header"); m_resourceDirs.insert("/resources"); } StringSet_CPtr dir_list(DirType type) { switch(type) { case SOURCE_DIR: return StringSet_CPtr(&m_sourceDirs, NullDeleter()); case HEADER_DIR: return StringSet_CPtr(&m_headerDirs, NullDeleter()); case RESOURCE_DIR: return StringSet_CPtr(&m_resourceDirs, NullDeleter()); default: return StringSet_CPtr(new StringSet); } } }; int main() { Target t; StringSet_CPtr sourceDirs = t.dir_list(SOURCE_DIR), headerDirs = t.dir_list(HEADER_DIR), resourceDirs = t.dir_list(RESOURCE_DIR), otherDirs = t.dir_list(OTHER); return 0; } 
0
source

There are directives that you can put in the default handler by default to say that it is not available. Compiler specific and not portable, but most compilers have something. I just don't remember how the GCC calls it.

EDIT found the syntax ...

 switch (whatever) { case blah : ...; break; default : __builtin_unreachable (); } 

As I said, this is a feature specific to GCC, however there is an equivalent to Visual C ++ written in different ways.

BTW - always return *((stringSet*) 0); .

EDIT Or create an exception.

In any case (with the exception of the exception, maybe), only if you are really sure that this will never happen.

0
source

If I understand you correctly ..........
This is how I do it with such switches. Two notes regarding this code:
1. I hate to use "&" ref and prefer "* const" to one (more readable), so please configure. It is the same in essence.
2. Did not test this code.

 const stringSet * const Target::dirList( const dirType type ) const { const stringSet * pRet = NULL; switch( type ) { case SOURCE_DIR: stringSet = m_sourceDirs; case HEADER_DIR: stringSet = m_headerDirs; case RESOURCE_DIR: stringSet = m_resourceDirs; } return pRet; } 
-2
source

All Articles