# question about A a = b? f1(x,y,z) : f2(o,p,q);

Discussion in 'C++' started by èƒ¡å®‡å…‰, Oct 11, 2012.

1. ### èƒ¡å®‡å…‰Guest

Think about the following code:

void func() {
...
A a = b? f1(x,y,z):f2(o,p,q);
...
}

1, class A doesn't not have default constructor.

2, x,y,z,o,p,q and the f1,f2 name are very long.

How can I make the code shorter?

If 1x is allowed, maybe I can write

auto F1 = [&]() {return f1(x,y,z);}
auto F2 = [&]() {return f2(o,p,q);}
A a = b? F1():F2();

If use c++ 03, how can I make the code shorter?

èƒ¡å®‡å…‰, Oct 11, 2012

2. ### Victor BazarovGuest

On 10/11/2012 6:37 AM, èƒ¡å®‡å…‰ wrote:
> Think about the following code:
>
> void func() {
> ...
> A a = b? f1(x,y,z):f2(o,p,q);
> ...
> }
>
> 1, class A doesn't not have default constructor.
>
> 2, x,y,z,o,p,q and the f1,f2 name are very long.

If one character names are "very long", perhaps there is some other help
required to the reader of the code.

> How can I make the code shorter?
>
> If 1x is allowed, maybe I can write
>
> auto F1 = [&]() {return f1(x,y,z);}
> auto F2 = [&]() {return f2(o,p,q);}
> A a = b? F1():F2();

Is that shorter? I don't think so. You just introduced two 'auto',
names 'F1' and 'F2', other symbols to define them. How is it shorter
than calling 'f1' and 'f2' directly?

> If use c++ 03, how can I make the code shorter?

You can't, really. Anything you do will be introduction of additional
code. Remove the spaces and you can shorten the code by 3 characters.

If class 'A' doesn't have a copy constructor and 'f1' and 'f2' return
some other type, then you *have to* use this form:

A a(b? f1(x,y,z):f2(o,p,q));

It's not shorter than

A a=b? ...

it has slightly different semantics.

V
--
I do not respond to top-posted replies, please don't ask

Victor Bazarov, Oct 11, 2012

3. ### Stefan van KesselGuest

On 2012-10-11 2:31 PM, Victor Bazarov wrote:
> If class 'A' doesn't have a copy constructor and 'f1' and 'f2' return
> some other type, then you *have to* use this form:
>
> A a(b? f1(x,y,z):f2(o,p,q));

Not necessarily. For example if A is constructable from the common type
of the return types of f1 and f2 and either the common type isn't a
built-in type or that constructor isn't explicit, then

A a(b? f1(x,y,z):f2(o,p,q));
and
A a = (b? f1(x,y,z):f2(o,p,q));

should both work.

For copy initialization (i.e. T x = y to work, T doesn't generally
have to have a copy constructor or assignment operator.

Stefan van Kessel, Oct 11, 2012
4. ### Stefan van KesselGuest

On 2012-10-11 12:37 PM, èƒ¡å®‡å…‰ wrote:
> Think about the following code:
>
> void func() {
> ...
> A a = b? f1(x,y,z):f2(o,p,q);
> ...
> }
>
> 1, class A doesn't not have default constructor.
>
> 2, x,y,z,o,p,q and the f1,f2 name are very long.
>
> How can I make the code shorter?
>
> If 1x is allowed, maybe I can write
>
> auto F1 = [&]() {return f1(x,y,z);}
> auto F2 = [&]() {return f2(o,p,q);}
> A a = b? F1():F2();
>
> If use c++ 03, how can I make the code shorter?

I assume you just want the
A a = b? f1(x,y,z):f2(o,p,q);
statement to be shorter / more readable, not the entire code.

If so, you could try the following:

const A& a1 = f1(x,y,z);
const A& a2 = f2(o,p,q);
A a = b?a1:a2;

If you haven't come across const references to temporaries before, you
may want to take a look at
http://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/

Stefan van Kessel, Oct 11, 2012
5. ### Stefan van KesselGuest

On 2012-10-11 5:57 PM, Stefan van Kessel wrote:
> I assume you just want the
> A a = b? f1(x,y,z):f2(o,p,q);
> statement to be shorter / more readable, not the entire code.
>
> If so, you could try the following:
>
> const A& a1 = f1(x,y,z);
> const A& a2 = f2(o,p,q);
> A a = b?a1:a2;

One caveat I forgot: with that code both f1 and f2 will actually be
called. So if performance matters, that's not a good alternative to your
code, where only either f1 or f2 will be called.

Stefan van Kessel, Oct 11, 2012
6. ### Victor BazarovGuest

On 10/11/2012 11:34 AM, Stefan van Kessel wrote:
> On 2012-10-11 2:31 PM, Victor Bazarov wrote:
>> If class 'A' doesn't have a copy constructor and 'f1' and 'f2' return
>> some other type, then you *have to* use this form:
>>
>> A a(b? f1(x,y,z):f2(o,p,q));

>
> Not necessarily. For example if A is constructable from the common type
> of the return types of f1 and f2 and either the common type isn't a
> built-in type or that constructor isn't explicit, then
>
> A a(b? f1(x,y,z):f2(o,p,q));
> and
> A a = (b? f1(x,y,z):f2(o,p,q));
>
> should both work.
>
> For copy initialization (i.e. T x = y to work, T doesn't generally
> have to have a copy constructor or assignment operator.

I believe you're mistaken in this. Here is the code I was thinking of:

struct A
{
double d_;
A(double d) : d_(d) {}

private:
A(const A&);
};

int f1(int x, int y, int z) { return 42; }
unsigned f2(unsigned p, unsigned o, unsigned q) { return 666; }

double foo(bool b)
{
A a = b? f1(1,2,3):f2(1,2,3); // error - copy c-tor private

return a.d_;
}

V
--
I do not respond to top-posted replies, please don't ask

Victor Bazarov, Oct 11, 2012
7. ### Stefan van KesselGuest

On 2012-10-11 9:06 PM, Victor Bazarov wrote:
> On 10/11/2012 11:34 AM, Stefan van Kessel wrote:
>> For copy initialization (i.e. T x = y to work, T doesn't generally
>> have to have a copy constructor or assignment operator.

>
> I believe you're mistaken in this. Here is the code I was thinking of:
>
> struct A
> {
> double d_;
> A(double d) : d_(d) {}
>
> private:
> A(const A&);
> };
>
> int f1(int x, int y, int z) { return 42; }
> unsigned f2(unsigned p, unsigned o, unsigned q) { return 666; }
>
> double foo(bool b)
> {
> A a = b? f1(1,2,3):f2(1,2,3); // error - copy c-tor private
>
> return a.d_;
> }

You're right, I apologize. MSVC compiles it without warning per default,
so I incorrectly assumed that it's valid code. But it is a nonstandard
extension of MSVC.

For copy initialization the type does have to be copy constructable. The
copy constructor won't necessarily be called but it has to be available.

Stefan van Kessel, Oct 11, 2012
8. ### Juha NieminenGuest

Victor Bazarov <> wrote:
>> auto F1 = [&]() {return f1(x,y,z);}
>> auto F2 = [&]() {return f2(o,p,q);}
>> A a = b? F1():F2();

>
> Is that shorter? I don't think so. You just introduced two 'auto',
> names 'F1' and 'F2', other symbols to define them. How is it shorter
> than calling 'f1' and 'f2' directly?

I don't think the point is it being shorter, but clearer.

Sometimes it's better to use additional variables even though they might
not be strictly mandatory, in order to make the code clearer and easier

In the above case I would prefer using references to the return values
of f1() and f2() rather than using lambdas.

Juha Nieminen, Oct 12, 2012
9. ### Victor BazarovGuest

On 10/12/2012 6:01 AM, Juha Nieminen wrote:
> Victor Bazarov <> wrote:
>>> auto F1 = [&]() {return f1(x,y,z);}
>>> auto F2 = [&]() {return f2(o,p,q);}
>>> A a = b? F1():F2();

>>
>> Is that shorter? I don't think so. You just introduced two 'auto',
>> names 'F1' and 'F2', other symbols to define them. How is it shorter
>> than calling 'f1' and 'f2' directly?

>
> I don't think the point is it being shorter, but clearer.

Clarity (like readability) is in the eye of the beholder. Since the use
of the argument list is now removed from the place where it matters, the
clarity is reduced, IMNSHO.

> Sometimes it's better to use additional variables even though they might
> not be strictly mandatory, in order to make the code clearer and easier

In that case the names of the variables (F1 vs f1 and F2 vs f2) does not
seem to present any advantage in terms of clarity. Again, that's just
my opinion, since clarity is not a universal trait.

> In the above case I would prefer using references to the return values
> of f1() and f2() rather than using lambdas.

.... which has different semantics as already has been mentioned.

V
--
I do not respond to top-posted replies, please don't ask

Victor Bazarov, Oct 12, 2012
10. ### StuartGuest

On 10/12/12 Drew Lawson wrote:
[snip]
> Longer lines that I personally prefer. Another try:
>
> A a = crypticDecidingFactor ? glorbifyWithFobnitzCorrection(hexDigitsPerProductID,
> historicalPriceTeaInChinaIn2008Euros,
> jennysPhoneNumber)
> temperatureEarlGrayHot22ndCentury,
> until12thOfNever);
>
> That's not great, but it is less painful to my eyes to read.
> (And it strongly calls out for some comments explaining what is happening.)

LOL, reading that was quite fun.

Where did you get these names from? I expect that a 100 years from now
people will no longer use "foo" or "bar" as example names, but
"glorbify" and "frobnitzicate". The last one made me laugh so hard that
I was glad that I was already sitting on the toilet at the time ...

Regards,
Stuart

Stuart, Oct 12, 2012
11. ### Juha NieminenGuest

Victor Bazarov <> wrote:
>> Sometimes it's better to use additional variables even though they might
>> not be strictly mandatory, in order to make the code clearer and easier

>
> In that case the names of the variables (F1 vs f1 and F2 vs f2) does not
> seem to present any advantage in terms of clarity. Again, that's just
> my opinion, since clarity is not a universal trait.

It was example code. The names are ostensibly not that non-telling in
the original code.

Juha Nieminen, Oct 12, 2012
12. ### PavelGuest

èƒ¡å®‡å…‰ wrote:
> Think about the following code:
>
> void func() {
> ...
> A a = b? f1(x,y,z):f2(o,p,q);
> ...
> }
>
> 1, class A doesn't not have default constructor.
>
> 2, x,y,z,o,p,q and the f1,f2 name are very long.
>
> How can I make the code shorter?
>
> If 1x is allowed, maybe I can write
>
> auto F1 = [&]() {return f1(x,y,z);}
> auto F2 = [&]() {return f2(o,p,q);}
> A a = b? F1():F2();
>
> If use c++ 03, how can I make the code shorter?
>

try (using RVO it should be equivalent):
namespace /* if not in the header */ {
A
createA(bool b, XP x, YP y, ZP z, OP o, PP p, QQ p) {
if (b)
return f1(x, y, z);
return f2(o, p, q);
}
}

void
func() {
...
A a(createA(b, x, y, z, o, p, q));
...
}

Above, [X-ZO-Q]P) are the names of the hand-selected best parameter type to pass
in x..q, respectively.

The savings are long f1, f2; also the parameter names in createA can be quite
short; also, it would be easier to debug f1 and f2 branches if you use a basic
debugger.

HTH
-Pavel

Pavel, Oct 14, 2012
13. ### èƒ¡å®‡å…‰Guest

åœ¨ 2012å¹´10æœˆ11æ—¥æ˜ŸæœŸå››UTC+8ä¸‹åˆ11æ—¶57åˆ†17ç§’ï¼ŒStefan van Kesselå†™é“ï¼š
> On 2012-10-11 12:37 PM, èƒ¡å®‡å…‰ wrote:
>
> > Think about the following code:

>
> >

>
> > void func() {

>
> > ...

>
> > A a = b? f1(x,y,z):f2(o,p,q);

>
> > ...

>
> > }

>
> >

>
> > 1, class A doesn't not have default constructor.

>
> >

>
> > 2, x,y,z,o,p,q and the f1,f2 name are very long.

>
> >

>
> > How can I make the code shorter?

>
> >

>
> > If 1x is allowed, maybe I can write

>
> >

>
> > auto F1 = [&]() {return f1(x,y,z);}

>
> > auto F2 = [&]() {return f2(o,p,q);}

>
> > A a = b? F1():F2();

>
> >

>
> > If use c++ 03, how can I make the code shorter?

>
>
>
>
>
> I assume you just want the
>
> A a = b? f1(x,y,z):f2(o,p,q);
>
> statement to be shorter / more readable, not the entire code.
>
>
>
> If so, you could try the following:
>
>
>
> const A& a1 = f1(x,y,z);
>
> const A& a2 = f2(o,p,q);
>
> A a = b?a1:a2;
>
>
>
> If you haven't come across const references to temporaries before, you
>
> may want to take a look at
>
> http://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/

const& a1 = f1(x,y,z)
const& a2 = f2(o,p,q)
it's diff with the A a = b? f1():f2().
The original code just execute one function, not both.

èƒ¡å®‡å…‰, Oct 15, 2012