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

Discussion in 'C++' started by 胡宇光, Oct 11, 2012.

  1. 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
    #1
    1. Advertising

  2. 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
    #2
    1. Advertising

  3. 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
    #3
  4. 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
    #4
  5. 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
    #5
  6. 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
    #6
  7. 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
    #7
  8. 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
    to read.

    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
    #8
  9. 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
    > to read.


    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
    #9
  10. 胡宇光

    Stuart Guest

    On 10/12/12 Drew Lawson wrote:
    [snip]
    > Longer lines that I personally prefer. Another try:
    >
    > A a = crypticDecidingFactor ? glorbifyWithFobnitzCorrection(hexDigitsPerProductID,
    > historicalPriceTeaInChinaIn2008Euros,
    > jennysPhoneNumber)
    > : frobnitzicateWithGlorbAdjustment(lolcatsPerCatLady,
    > 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
    #10
  11. 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
    >> to read.

    >
    > 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
    #11
  12. 胡宇光

    Pavel Guest

    胡宇光 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
    #12
  13. 在 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
    #13
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. sean
    Replies:
    1
    Views:
    589
    Cowboy \(Gregory A. Beamer\)
    Oct 20, 2003
  2. =?Utf-8?B?UnlhbiBTbWl0aA==?=

    Quick Question - Newby Question

    =?Utf-8?B?UnlhbiBTbWl0aA==?=, Feb 14, 2005, in forum: ASP .Net
    Replies:
    4
    Views:
    645
    Iain Norman
    Feb 16, 2005
  3. =?Utf-8?B?YW5kcmV3MDA3?=

    question row filter (more of sql query question)

    =?Utf-8?B?YW5kcmV3MDA3?=, Oct 5, 2005, in forum: ASP .Net
    Replies:
    2
    Views:
    940
    Scott Allen
    Oct 6, 2005
  4. Philip Meyer
    Replies:
    0
    Views:
    414
    Philip Meyer
    Nov 30, 2003
  5. Bit Byte
    Replies:
    1
    Views:
    836
    Teemu Keiski
    Jan 28, 2007
Loading...

Share This Page