3

(Note: I know of Boost.Format, I'm looking for a better way to do the following.)
First a use-case example: In some countries, you name a person by calling his / her surname first and the forename last, while in other countries it's the exact opposite.

Now, for my code, I currently solve this with Boost.Format in the following fashion:

#include <boost/format.hpp>
#include <iostream>
#include <stdlib.h>
#include <utility>

int main(){
    using namespace boost;

    int pos1 = 2, pos2 = 1;
    char const* surname = "Surname", *forename = "Forename";

    // decision on ordering here
    bool some_condition = false;

    if(some_condition)
      std::swap(pos1,pos2);

    char buf[64];
    sprintf(buf,"Hello %c%d%c %c%d%c",'%',pos1,'%','%',pos2,'%');
    // buf == "Hello %[pos1]% %[pos2]%"; with [posN] = value of posN

    std::cout << format(buf) % surname % forename;
}

Now, I would rather have it like this, i.e., everything in the format line:

std::cout << format("Hello %%1%% %%2%%") % pos1 % pos2 % surname % forename;

But sadly, that doesn't work, as I get a nice parsing exception.

Is there any library to have real positional formatting? Or even a way to achieve this with Boost.Format that I don't know of?

Xeo
  • 129,499
  • 52
  • 291
  • 397
  • 1
    +1 for have the courage to show us: "int pos1 = 2, pos2 = 1;" – Pete Wilson May 17 '11 at 20:53
  • and the reason why you can't just `std::swap(surname, forename);` in situ is...? – sehe May 17 '11 at 20:53
  • @Pete: that _is_ interesting, indeed – sehe May 17 '11 at 20:54
  • @sehe: That reason is another good question in itself. ;) But this is just a simple case, it might get more complicated with the word ordering. – Xeo May 17 '11 at 20:55
  • @Pete: Gotta admit, that comment made me chuckle. :) – Xeo May 17 '11 at 20:55
  • @Xeo: ok, understood. I'll withdraw my answer as it doesn't answer the spirit of the question then – sehe May 17 '11 at 20:58
  • OT: thx for showing me the `` markup. Yay! More markup – sehe May 17 '11 at 21:13
  • @sehe: Try combining `` and `` for super-small fonts. :) Also, that's basic HTML which is supported, not markup per se. – Xeo May 17 '11 at 21:14
  • @Xeo: well, I wasn't aware of the support in here. (Other Html-ish markup doesn't work too well on SO). Also, to nitpick my own misnomer: it should have been Markdown anyways. – sehe May 17 '11 at 21:16
  • 2
    What are the odds that the word ordering is the only thing you need to change? In locales with different order of the names, is "Hello" really a proper greeting? What about middle name or initial? Or titles - "Professor Dr Ing Schultz"? – Bo Persson May 17 '11 at 21:20
  • @Bo: Simple example gone too simple. :( Valid claim though, but this idea is somehow fixed inside my head. You might consider user settings to reorder certain output or display. :) – Xeo May 17 '11 at 21:37

6 Answers6

1

In my opinion, Boost.Spirit.Karma is the definitive modern output formatting library.

ildjarn
  • 62,044
  • 9
  • 127
  • 211
  • True, but not very relevant to this question? You'd have write specific formatting rule for the respective localized formatting preferences, much like the separate format strings – sehe May 17 '11 at 20:57
  • After reading the motivation from Xeo, this gets my +1. Deffo most versatile. Karma will make the model/view separation easier than Boost Format. A lot. Use FUSION struct adaptation and you'll be able to 'databind' directly to your [DTO](http://en.wikipedia.org/wiki/Data_transfer_object) – sehe May 17 '11 at 21:00
  • @sehe : How is it not relevant to "*Is there any library to have real positional formatting?*"? – ildjarn May 17 '11 at 21:00
  • @sehe : No idea what you mean by that; in any case, the Karma generator could use a semantic action that has the localized formatting logic so only a singular grammar need exist regardless of desired output order. – ildjarn May 17 '11 at 21:03
  • @ildjam: yeah I'm with you since a while; however, I do have a feeling that we're burying the wretched conditional in a pretty lambda that we can pass off as 'metadata'. Xeo's pseudo code example shows more of a statically defined, general-purpose multi-pass formatting engine instead. No special-purpose conditionals. At all. – sehe May 17 '11 at 21:10
  • Karma doesn't support positional arguments or format strings at all. – vitaut Dec 28 '12 at 14:57
1

This is the Message Formatting part of Boost.Locale which is similar to GNU gettext.

In it you would write:

cout << format(translate("Hello {1} {2}!")) % forename % surname << endl;

And then a translator would translate the string using message catalogs:

msgid "Hello {1} {2}!"
msgstr "こんにちは {2}-さん!"
dalle
  • 18,057
  • 5
  • 57
  • 81
0

You can do this by applying format recursively:

cout << format(str(format("%%%1%%% %%%2%%%") % pos1 % pos2)) % surname % forname;

However, I would recommend using something like GNU gettext instead.

vitaut
  • 49,672
  • 25
  • 199
  • 336
0

I'd simply swap the values that you interpolating

std::swap(surname, forename)

That'll do the job. If you don't want to mess with them, have references:

const std::string& param1(bSwapThem? forename : surname);
const std::string& param2(bSwapThem? surname  : forename);

KISS

sehe
  • 374,641
  • 47
  • 450
  • 633
0

Sounds like something that should be in the system locale but it doesn't look like it's currently supported.

What about the simple way?

   if(some_condition)
      std::cout << surname << " " << forename;
   else
      std::cout << forename << " " << surname;
Jay
  • 13,803
  • 4
  • 42
  • 69
0

I would have used ?:

char const* surname = "Surname", *forename = "Forename";
bool swapFlag = (some_condition) ? true : false;

std::cout << "Hello " << (swapFlag ? surname : forename) << " " << (!swapFlag ? surname : forename) << std::endl;
Valkea
  • 1,216
  • 1
  • 12
  • 26