From: Vidar Hasfjord on
In C++ you cannot declare new user-defined operators, i.e. it is
impossible to define a new operator token with a specified precedent
and meaning, e.g. the euro symbol (EURO) to convert a value into euro
cents.

It is possible to simulate this to some degree using an object of a
user-defined class with an operator overload. For example, with an
"operator" object named E with a operator % overload, we can write (E%
v) to mean some operation on v.

I've found great utility for this idiom in two areas: error code
checking and resource string loading (internationalisation). For
example, with E% as a error-check operator and SL% as a string load
operator I can write:

E%DeleteFile (file); // throws on error

and

string caption = SL%IDS_VALIDATION_ERROR; // i18n
string message = format (SL%IDS_OUT_OF_RANGE) % value;
MessageBox (message, caption);

While I think such operator use may be considered obfuscation in the
general case, I think it has merits when it forms an idiom used in
large parts of the code. But would this code pass your code review?
Opinions welcome.

Regards,
Vidar Hasfjord

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Michael Aaron Safyan on
Using operator% in this manner would never pass my code review, because
this usage has absolutely nothing to do with taking the modulus of a
value, and -- therefore -- this usage is unintuitive.


For the first example, why write "to_euros % some_value" when you can
just as easily write "to_euros(some_value)"?

For the second example, functions should throw exceptions, by default.
If you don't want a function to throw exceptions, then they should be
explicitly disabled as in the following:

disable_exceptions{
// code which normally throws exceptions ceases to throw exceptions
}

The above can be implemented with something along the lines of:

class ExceptionDisabler
{
public:
ExceptionDisabler() : _test(true) {
ExceptionManager::push(false); // disable
}
~ExceptionDisabler(){
ExceptionManager::pop(); // restore
}

void operator++(){ _test = false; }
void operator++(int){ _test = false; }
operator bool()const{ return _test; }
private:
bool _test;
};

#define TOKENCAT(X,Y) TOKENCAT2(X,Y)
#define TOKENCAT2(X,Y) X ## Y

#define disable_exceptions \
for ( ExceptionDisabler TOKENCAT(ed,__LINE__); \
TOKENCAT(ed,__LINE__); \
TOKENCAT(ed,__LINE__)++ ) \

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Martin T. on
Vidar Hasfjord wrote:
> In C++ you cannot declare new user-defined operators, i.e. it is
> impossible to define a new operator token with a specified precedent
> and meaning, e.g. the euro symbol (EURO) to convert a value into euro
> cents.
>
> It is possible to simulate this to some degree using an object of a
> user-defined class with an operator overload. For example, with an
> "operator" object named E with a operator % overload, we can write (E%
> v) to mean some operation on v.
>
> I've found great utility for this idiom in two areas: error code
> checking and resource string loading (internationalisation). For
> example, with E% as a error-check operator and SL% as a string load
> operator I can write:
>
> E%DeleteFile (file); // throws on error
>
> and
>
> string caption = SL%IDS_VALIDATION_ERROR; // i18n
> string message = format (SL%IDS_OUT_OF_RANGE) % value;
> MessageBox (message, caption);
>
> While I think such operator use may be considered obfuscation in the
> general case, I think it has merits when it forms an idiom used in
> large parts of the code. But would this code pass your code review?
> Opinions welcome.
>

What are the merits of this solution over just using a set for ctors for
the E and SL classes?
E(DeleteFile(file));
string message = format (SL(IDS_OUT_OF_RANGE)) % value;

br,
Martin

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Edward Rosten on
On Apr 14, 9:25 pm, Michael Aaron Safyan <michaelsaf...(a)aim.com>
wrote:
> Using operator% in this manner would never pass my code review, because
> this usage has absolutely nothing to do with taking the modulus of a
> value, and -- therefore -- this usage is unintuitive.

Out of interest, would any of the following code pass your review:

cout << "Hello, world." << endl;

or

string s;
....
s += "Hello, world.";

These expressions have respectively nothing to do with bit-shifting or
addition.

-Ed

--
(You can't go wrong with psycho-rats.)(http://mi.eng.cam.ac.uk/~er258)

/d{def}def/f{/Times s selectfont}d/s{11}d/r{roll}d f 2/m{moveto}d -1
r 230 350 m 0 1 179{ 1 index show 88 rotate 4 mul 0 rmoveto}for/s 12
d f pop 235 420 translate 0 0 moveto 1 2 scale show showpage

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Alberto Ganesh Barbati on
Michael Aaron Safyan ha scritto:
>
> For the second example, functions should throw exceptions, by default.
> If you don't want a function to throw exceptions, then they should be
> explicitly disabled as in the following:
>
> disable_exceptions{
> // code which normally throws exceptions ceases to throw exceptions
> }
>

I really don't see the relationship with the OP's example. Moreover, it
seems to me that it's a bad idea in the first place: if a function is
designed to throw an exception to return an error condition and you
disallow that, what should the function do to return the error
condition? If the function calls a library function which is not under
your control, how can you disallow exception thrown by the library
function? In the end, it's much safer to wrap the code in a try/catch
block rather than using your approach.

> The above can be implemented with something along the lines of:
>
> class ExceptionDisabler
> {
> public:
> ExceptionDisabler() : _test(true) {
> ExceptionManager::push(false); // disable
> }
> ~ExceptionDisabler(){
> ExceptionManager::pop(); // restore
> }
>
> void operator++(){ _test = false; }
> void operator++(int){ _test = false; }
> operator bool()const{ return _test; }
> private:
> bool _test;
> };
>
> #define TOKENCAT(X,Y) TOKENCAT2(X,Y)
> #define TOKENCAT2(X,Y) X ## Y
>
> #define disable_exceptions \
> for ( ExceptionDisabler TOKENCAT(ed,__LINE__); \
> TOKENCAT(ed,__LINE__); \
> TOKENCAT(ed,__LINE__)++ ) \
>

BTW, there is simpler a way of implementing this that doesn't require a
loop:

class ExceptionDisabler
{
public:
ExceptionDisabler(int) {
ExceptionManager::push(false); // disable
}
~ExceptionDisabler() {
ExceptionManager::pop(); // restore
}

operator bool() const { return false; }
};

#define TOKENCAT(X,Y) TOKENCAT2(X,Y)
#define TOKENCAT2(X,Y) X ## Y

#define disable_exceptions \
if (ExceptionDisabler TOKENCAT(ed,__LINE__) = 0) {} else

HTH,

Ganesh

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]