7

I think many of you have this kind of code somewhere:

int foo;
switch (bar) {
  case SOMETHING: foo = 5;  break;
  case STHNELSE:  foo = 10; break;
  ...
}

But this code has some drawbacks:

  • You can easily forget a "break"
  • The foo variable is not const while it should be
  • It's just not beautiful

So I started wondering if there was a way to "improve" this kind of code, and I got this little idea:

const int foo = [&]() -> int {
  switch (bar) {
    case SOMETHING: return 5;
    case STHNELSE:  return 10;
    ...
  }
}();

Note: the first pair of parentheses it not mandatory, but MSVC++ doesn't support this yet

You can use the same trick with if-else where the ternary operator would be too complicated, variables that require to be passed by pointers to be initialized (like for DirectX functions), etc.

My questions are:

  • Is there anything wrong with this code that I didn't see?
  • Do you find it better than the one above?
  • g++ seems to inline the function, but do you think that all compilers will do so?

EDIT: this is what I mean by "DirectX functions"

_xAudio2 = [&]() -> std::shared_ptr<IXAudio2> {
    IXAudio2* ptr = nullptr;
    if (FAILED(XAudio2Create(&ptr, xAudioFlags, XAUDIO2_DEFAULT_PROCESSOR)))
        throw std::runtime_error("XAudio2Create failed");
    return std::shared_ptr<IXAudio2>(ptr, [](IUnknown* ptr) { ptr->Release(); });
}();
4
  • 4
    Neat trick! But I would go one step beyond and turn the lambda into a named function "int EnumToFoo(Enum)" anyway: less clutter in the calling function and automatically documentated with a well-descriptive name ;). Commented Aug 9, 2010 at 10:23
  • I'm with sjoerd - I would always refactor any mapping function - switch or otherwise Commented Aug 9, 2010 at 10:32
  • 1
    In this case it could be worth coding an external function, but I don't see myself creating a function just to build a DirectX object for example Commented Aug 9, 2010 at 10:59
  • This was covered in Herb Sutter's "Lambdas, Lambdas everywhere" presentation. nwcpp.org/images/stories/lambda.pdf Page 32, top slide. Commented Mar 5, 2012 at 18:17

2 Answers 2

3

This is a fairly common technique in other languages. Almost every high-level feature of Scheme is defined in terms of lambdas that are immediately called.

In JavaScript it is the basis of the "module pattern", e.g.

var myModule = (function() {

    // declare variables and functions (which will be "private")

    return {
       // populate this object literal with "public" functions
    };

})();

So an anonymous function is declared and immediately called, so that any internal details are hidden and only the return value is exposed externally.

The only downsides is that on a casual reading of the code, the return statements will appear to be returning from the outer function (there was intense controversy about this during the Java lambda wars). But this is just something you have to get used to once your language has lambdas.

There are many language features in an imperative language like C++ which would benefit from being able to return a value (rather than being like a void function). For example, if has an alternative, the tertiary operator expr ? a : b.

In Ruby pretty much all statements can be evaluated, so there is no need for a separate syntax where a return value can be supplied. If C++ worked that way, this would mean things like:

auto result = try
{
    getIntegerSomehow();
}
catch (const SomeException &)
{
    0;
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, I'm not so used to using functional languages
0

I don't see any reason at all to use a switch case in such a case. Any decent compiler will generate just as fast code with if statements as with a switch case.

if(bar == SOMETHING)
   foo = 5;
else if(bar == STHNELSE)
   foo = 10;

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.