On 02/13/2018 10:37 PM, Martin Sebor wrote: > On 02/13/2018 01:59 PM, Manuel López-Ibáñez wrote: >> > Here's a sketch of what I tried to do: > > struct IntegerConverter > { > union { > tree t; > unsigned HOST_WIDE_INT hwi; > // buffer for offset_int, wide_int, etc. > } value; > > IntegerConverter (tree t) > { > value.t = t; > } > > IntegerConverter (unsigned HOST_WIDE_INT x) > { > value.x = x; > } > > ... > }; > > void error_n (int, const IntegerConverter &, const char*, ...); > ... > > With that, the call > > error_n (loc, t, "%E thing", "%E things", t); > > works when t is a tree, and the call to the same function > > error_n (loc, i, "%wu thing", "%wu things", i); > > also works when i is a HOST_WIDE_INT. I chose this approach > to avoid introducing additional overloads of the error_n() > functions.
Instead of a class that has to have a constructor for every type you want to pass as plural selector to the _n functions, which increases coupling, I'd suggest using a conversion function, and overload that. I.e., something like, in the core diagnostics code: static inline unsigned HOST_WIDE_INT as_plural_form (unsigned HOST_WIDE_INT val) { return val; } /* In some tree-diagnostics header. */ static inline unsigned HOST_WIDE_INT as_plural_form (tree t) { // extract & return a HWI } /* In some whatever-other-type-diagnostics header. */ static inline unsigned HOST_WIDE_INT as_plural_form (whatever_other_type v) { // like above } and then you call error_n and other similar functions like this: error_n (loc, u, "%u thing", "%u things", u); error_n (loc, as_plural_form (u), "%u thing", "%u things", u); error_n (loc, as_plural_form (t), "%E thing", "%E things", t); error_n (loc, as_plural_form (i), "%wu thing", "%wu things", i); This is similar in spirit to std::to_string, etc. BTW, the "plural_form" naming above comes from ngettext's documentation of the N parameter: char * ngettext (const char *msgid1, const char *msgid2, unsigned long int n); "The parameter n is used to determine the plural form." Pedro Alves