5

Essentially the same as this question, but for C++.

The simplest way to do this would be:

if (condition) {
    a = f(x);
} else {
    b = f(x);
}

While this meets my needs, it has always been bugging me that I've had to repeat typing f(x) twice, not to mention expanding the code out over so many lines when only one line will be executed. What if I have a larger set of destination variables to choose from?

switch(condition variable) {
case 1:
    var1 = f(x);
    break;
case 2:
    var2 = f(x);
    break;
...
case y:
    vary = f(x);
    break;
}

This looks very inelegant to me.

Is there anything in C++ that essentially allows me to do the following?

do-something-that-returns-a-lvalue = f(x);

Pardon me if it's not called a lvalue, I'm still relatively new to C++. But you guys know what I mean - the destination variable to assign a value to.

Community
  • 1
  • 1
thegreatjedi
  • 2,788
  • 4
  • 28
  • 49
  • You can certainly write a function that returns a reference and assign to that. – Mark Ransom Dec 11 '15 at 01:29
  • How do I do that? What is the return type of the function supposed to look like? – thegreatjedi Dec 11 '15 at 01:31
  • While it is not the direct answer to the question, `fval = f(x); if (condition) a = fval; else b = fval` is much more legible to me, while still being DRY. – Amadan Dec 11 '15 at 01:32
  • @Amadan I understand the DRY principle, but it has always bugged me that, even when I do that, fval is still to me a form of repetition. That's why I call it inelegant - it seems like a solution but really isn't. – thegreatjedi Dec 11 '15 at 01:35
  • this strikes me as a novice using numbered variables instead of an array. if you had `T vars[size]` then `vars[condition_variable] = f(x)`. of course you'd be better with `std::vector` or `std::array` – Ryan Haining Dec 11 '15 at 01:41
  • Any reason you can't store these named variables instead as a vector of some common type? From there it'd just be a matter of selecting an index. – Brian Rodriguez Dec 11 '15 at 01:49
  • Problem is, I can't mathematically calculate which index to assign to. It's not ordered. – thegreatjedi Dec 11 '15 at 01:57

4 Answers4

8

You can form a reference or a pointer to the variable you want to assign.

(condition ? a : b) = f(x);  // reference

The above version was suggested by aschepler in a comment.

*(condition ? &a : &b) = f(x);  // pointer

The reference version is basically equivalent to the following more verbose example using a helper function.

template <typename T>
T&
conditional_reference(bool pred, T& yes, T& no) noexcept
{
  return pred ? yes : no;
}

// And then later

conditional_reference(condition, a, b) = f(x);

My point is that your traditional if then else control flow is probably still the best choice in terms of code clarity.

If the source of the assignment is a more complex expression than just f(x), you may store its result in a temporary variable and then only assign that variable in your conditional. C++11 move semantics make the use of such temporaries acceptable in many cases.

5gon12eder
  • 24,280
  • 5
  • 45
  • 92
  • 3
    If `a` and `b` have the same type, plain old `(condition ? a : b) = f(x);` will do. – aschepler Dec 11 '15 at 01:33
  • @aschepler Honestly, I was a little surprised that this works but thinking through it, sure, it does. I'll remember that. – 5gon12eder Dec 11 '15 at 01:39
  • This is most probably the exact solution I'm looking for. Thanks! I'll accept this as the answer. – thegreatjedi Dec 11 '15 at 01:41
  • @thegreatjedi so you weren't actually looking for more than two variables? – Ryan Haining Dec 11 '15 at 01:43
  • Of course, you can extend the pattern to more than two variables `((y == 1) ? a : (y == 2) ? b : c) = f(x)` but it won't scale very well. – 5gon12eder Dec 11 '15 at 01:51
  • The only issue appears whenever `a` and `b` are not exactly the same types, but one is convertible to the other. In that case, the result of the ternary operator is a rvalue, which you cannot assign to. – vsoftco Dec 11 '15 at 02:34
6

If you can decide which variable to assign to at compile time, then you can get away with this very clean and zero-overhead approach:

std::get<constexpr_indexer()>(std::tie(var1, var2, var3, var4)) = f(x);

std::get, std::tie

Brian Rodriguez
  • 4,250
  • 1
  • 16
  • 37
  • Thanks for this answer! I think this one in particular is very good to know, even though unfortunately it is restricted to compile time only. Too bad I can't choose multiple answers. – thegreatjedi Dec 11 '15 at 01:42
2

You can assign a pointer variable (e.g double * p) in your switch statement.

switch(condition variable) {
case 1:
    p = & var1;
    break;
case 2:
    p = & var2;
    break;
...
case y:
    p = & vary;
    break;
}

Then you can do this after you switch statement.

*p = f(x);
Anon Mail
  • 4,660
  • 1
  • 18
  • 21
  • This doesn't really solve the problem. Now I've to do the switch statement with the pointer variable on the left hand side. It's essentially the same thing. My question is whether the switch statement can be avoided and the same functionality consolidated into a single line or something to that effect. – thegreatjedi Dec 11 '15 at 01:33
  • @thegreatjedi you can use the ternary operator as 5gon12eder suggested. But any more that two conditions and the code will become unreadable. – Anon Mail Dec 11 '15 at 01:36
0

Like the question you linked to, you still have an XY problem. Why do you need this? Why do you feel writing more code that's potentially unreadable and unmaintainable less elegant than a simple if/else condition? But the core of the question is, in what valid scenario would you have 26 (following along with the alphabet) variables with the same value?

Unless you have a scenario similar to the original question (Binary Search Tree) just stick with one variable.

Please read DRY unrelated, but nearly identical, code:

You don't do DRY because someone wrote it in a book somewhere that it's good to do, you do DRY because it actually has tangible benefits.

Community
  • 1
  • 1
  • @Downvoters Seeing the variability in the answers with no clear specification of what the OP actually wants other than to avoid "DRY" is a strong indication of "unclear what you're asking" or "too broad". – user5666873 Dec 11 '15 at 01:41
  • If you think that a question is “too broad” or it is “unclear what you're asking”, the recommended procedure is to ask for narrowing or clarifying the question and if that doesn't work, flagging it for closure. It is not an excuse to consequently post broad or unclear answers. That said, I didn't feel your answer deserves down-vote. – 5gon12eder Dec 11 '15 at 01:48
  • 1
    I have encountered instances across different programs where all I want to do is "choose which variable to assign to". I know there are various ways to choose which variable's value to use, so naturally I'm just curious if the same is true for vice versa, seeing as I've routinely encountered a need for it. To me, something like a switch-case statement should be used when different cases have significantly different code, not for repeating one statement n times. I'm not asking to solve one problem here and now, but to learn what techniques are available to me. – thegreatjedi Dec 11 '15 at 01:54